diff --git a/andmore-core/features/feature/feature.xml b/andmore-core/features/feature/feature.xml index f8ca1f0c..1e756cdb 100644 --- a/andmore-core/features/feature/feature.xml +++ b/andmore-core/features/feature/feature.xml @@ -28,7 +28,6 @@ version="0.0.0"/> - diff --git a/andmore-core/plugins/android.codeutils/.classpath b/andmore-core/plugins/android.codeutils/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/android.codeutils/.classpath +++ b/andmore-core/plugins/android.codeutils/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/android.codeutils/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/android.codeutils/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/android.codeutils/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/android.codeutils/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/android.codeutils/META-INF/MANIFEST.MF b/andmore-core/plugins/android.codeutils/META-INF/MANIFEST.MF index 842c005b..677a0a19 100644 --- a/andmore-core/plugins/android.codeutils/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/android.codeutils/META-INF/MANIFEST.MF @@ -1,34 +1,34 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.codeutils;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.codeutils.CodeUtilsActivator -Bundle-Vendor: %providerName -Bundle-ActivationPolicy: lazy -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.codeutils.codegeneration, - org.eclipse.andmore.android.codeutils.db.actions, - org.eclipse.andmore.android.codeutils.db.utils, - org.eclipse.andmore.android.codeutils.wizards, - org.eclipse.andmore.android.db.deployment, - org.eclipse.andmore.android.db.wizards.model, - org.eclipse.andmore.wizards.buildingblocks -Bundle-ClassPath: . -Require-Bundle: org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.datatools.connectivity, - org.eclipse.datatools.modelbase.sql, - org.eclipse.jdt.ui, - org.eclipse.ui, - org.eclipse.ui.ide, - org.eclipse.andmore.android, - org.eclipse.andmore.android.common, - org.eclipse.jface.text, - org.eclipse.datatools.connectivity.sqm.core, - org.eclipse.jdt.core, - org.apache.xerces, - org.eclipse.datatools.sqltools.data.ui, - org.eclipse.sequoyah.localization.tools -Import-Package: org.eclipse.ui.texteditor +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.codeutils;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.codeutils.CodeUtilsActivator +Bundle-Vendor: %providerName +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.codeutils.codegeneration, + org.eclipse.andmore.android.codeutils.db.actions, + org.eclipse.andmore.android.codeutils.db.utils, + org.eclipse.andmore.android.codeutils.wizards, + org.eclipse.andmore.android.db.deployment, + org.eclipse.andmore.android.db.wizards.model, + org.eclipse.andmore.wizards.buildingblocks +Bundle-ClassPath: . +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.datatools.connectivity, + org.eclipse.datatools.modelbase.sql, + org.eclipse.jdt.ui, + org.eclipse.ui, + org.eclipse.ui.ide, + org.eclipse.andmore.android, + org.eclipse.andmore.android.common, + org.eclipse.jface.text, + org.eclipse.datatools.connectivity.sqm.core, + org.eclipse.jdt.core, + org.apache.xerces, + org.eclipse.datatools.sqltools.data.ui, + org.eclipse.sequoyah.localization.tools +Import-Package: org.eclipse.ui.texteditor diff --git a/andmore-core/plugins/android.win32.x86_64/.classpath b/andmore-core/plugins/android.win32.x86_64/.classpath index 0b1bcf94..7498423d 100644 --- a/andmore-core/plugins/android.win32.x86_64/.classpath +++ b/andmore-core/plugins/android.win32.x86_64/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/android.win32.x86_64/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/android.win32.x86_64/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/android.win32.x86_64/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/android.win32.x86_64/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/android.win32.x86_64/META-INF/MANIFEST.MF b/andmore-core/plugins/android.win32.x86_64/META-INF/MANIFEST.MF index 7acf665a..b3ee5082 100644 --- a/andmore-core/plugins/android.win32.x86_64/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/android.win32.x86_64/META-INF/MANIFEST.MF @@ -1,10 +1,10 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.andmore.android.win32.x86_64;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: %Bundle-Vendor -Fragment-Host: org.eclipse.andmore.android -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: fragment -Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64)) +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.andmore.android.win32.x86_64;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: %Bundle-Vendor +Fragment-Host: org.eclipse.andmore.android +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: fragment +Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64)) diff --git a/andmore-core/plugins/android/.classpath b/andmore-core/plugins/android/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/android/.classpath +++ b/andmore-core/plugins/android/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/android/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/android/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/android/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/android/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/android/META-INF/MANIFEST.MF b/andmore-core/plugins/android/META-INF/MANIFEST.MF index 7f7ada1e..51e0e04d 100644 --- a/andmore-core/plugins/android/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/android/META-INF/MANIFEST.MF @@ -1,46 +1,48 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.AndroidPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.ui.ide, - org.eclipse.andmore.android.common, - org.eclipse.andmore.android.logger.collector, - org.eclipse.core.runtime, - org.eclipse.core.filesystem, - org.eclipse.andmore, - org.eclipse.andmore.ddms, - org.eclipse.jdt.core, - org.eclipse.jface.text, - org.apache.xerces, - org.eclipse.ui.console, - org.eclipse.sequoyah.localization.tools, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.debug.ui, - org.eclipse.core.expressions, - org.eclipse.andmore.base, - org.eclipse.jdt.ui, - org.apache.commons.net;bundle-version="1.4.1", - org.apache.oro;bundle-version="2.0.8" -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Export-Package: - org.eclipse.andmore.android, - org.eclipse.andmore.android.devices, - org.eclipse.andmore.android.i18n, - org.eclipse.andmore.android.model, - org.eclipse.andmore.android.multidex, - org.eclipse.andmore.android.nativeos, - org.eclipse.andmore.android.sdkmanager, - org.eclipse.andmore.android.utilities, - org.eclipse.andmore.android.wizards.elements, - org.eclipse.andmore.android.wizards.installapp, - org.eclipse.andmore.android.wizards.monkey -Bundle-ActivationPolicy: lazy -Import-Package: org.eclipse.equinox.security.storage, - org.eclipse.ui.console -Bundle-ClassPath: . +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.AndroidPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.ui.ide, + org.eclipse.andmore.android.common, + org.eclipse.andmore.android.logger.collector, + org.eclipse.core.runtime, + org.eclipse.core.filesystem, + org.eclipse.andmore, + org.eclipse.andmore.ddms, + org.eclipse.jdt.core, + org.eclipse.jface.text, + org.apache.xerces, + org.eclipse.ui.console, + org.eclipse.sequoyah.localization.tools, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.debug.ui, + org.eclipse.core.expressions, + org.eclipse.jdt.ui, + org.apache.commons.net;bundle-version="1.4.1", + org.apache.oro;bundle-version="2.0.8", + org.eclipse.andmore.swt;bundle-version="0.5.2", + org.eclipse.andmore.ddmuilib;bundle-version="0.5.2", + org.eclipse.andmore.sdkuilib;bundle-version="0.5.2" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Export-Package: + org.eclipse.andmore.android, + org.eclipse.andmore.android.devices, + org.eclipse.andmore.android.i18n, + org.eclipse.andmore.android.model, + org.eclipse.andmore.android.multidex, + org.eclipse.andmore.android.nativeos, + org.eclipse.andmore.android.sdkmanager, + org.eclipse.andmore.android.utilities, + org.eclipse.andmore.android.wizards.elements, + org.eclipse.andmore.android.wizards.installapp, + org.eclipse.andmore.android.wizards.monkey +Bundle-ActivationPolicy: lazy +Import-Package: org.eclipse.equinox.security.storage, + org.eclipse.ui.console +Bundle-ClassPath: . diff --git a/andmore-core/plugins/android/src/org/eclipse/andmore/android/SdkUtils.java b/andmore-core/plugins/android/src/org/eclipse/andmore/android/SdkUtils.java index 393fc889..0fe79f7c 100644 --- a/andmore-core/plugins/android/src/org/eclipse/andmore/android/SdkUtils.java +++ b/andmore-core/plugins/android/src/org/eclipse/andmore/android/SdkUtils.java @@ -1,950 +1,951 @@ -/* - * Copyright (C) 2012 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 org.eclipse.andmore.android; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import org.eclipse.andmore.AndmoreAndroidPlugin; -import org.eclipse.andmore.android.common.IAndroidConstants; -import org.eclipse.andmore.android.common.exception.AndroidException; -import org.eclipse.andmore.android.common.log.AndmoreLogger; -import org.eclipse.andmore.android.common.utilities.FileUtil; -import org.eclipse.andmore.android.i18n.AndroidNLS; -import org.eclipse.andmore.android.manifest.AndroidProjectManifestFile; -import org.eclipse.andmore.android.model.manifest.AndroidManifestFile; -import org.eclipse.andmore.android.model.manifest.dom.AndroidManifestNode; -import org.eclipse.andmore.android.model.manifest.dom.UsesSDKNode; -import org.eclipse.andmore.internal.sdk.AndroidTargetData; -import org.eclipse.andmore.internal.sdk.Sdk; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.osgi.util.NLS; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -import com.android.SdkConstants; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.internal.widgets.MessageBoxLog; -import com.android.utils.ILogger; - -/** - * DESCRIPTION: This class provides utility methods related to the Android SDK.
- * USAGE: See public methods - */ - -public class SdkUtils { - public static final int API_LEVEL_FOR_PLATFORM_VERSION_3_0_0 = 11; - - public static final String VM_CONFIG_FILENAME = "config.ini"; //$NON-NLS-1$ - - public static final String USERIMAGE_FILENAME = "userdata-qemu.img"; //$NON-NLS-1$ - - public static final String[] STATEDATA_FILENAMES = { "cache.img", "userdata.img", "emulator-user.ini" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - }; - - public static final String EMU_CONFIG_SKIN_NAME_PROPERTY = "skin.name"; //$NON-NLS-1$ - - /** - * Gets the current SDK object - */ - public static Sdk getCurrentSdk() { - return Sdk.getCurrent(); - } - - /** - * Gets the directory where the configured SDK is located - */ - public static String getSdkPath() { - String sdkDir = null; - Sdk sdk = getCurrentSdk(); - if (sdk != null) { - sdkDir = sdk.getSdkOsLocation(); - } - return sdkDir; - } - - /** - * Gets the path to the "tools" folder of the SDK - * - * @return - */ - public static String getSdkToolsPath() { - return AndmoreAndroidPlugin.getOsSdkToolsFolder(); - } - - public static IAndroidTarget getTargetByAPILevel(Integer apiLevel) { - IAndroidTarget returnTarget = null; - - for (IAndroidTarget target : getAllTargets()) { - if (target.getVersion().getApiLevel() == apiLevel) { - returnTarget = target; - } - } - return returnTarget; - } - - /** - * Get the AAPT application path from an android target if null is passed, - * try to get some aapt - * - * @param target - * @return - */ - public static String getTargetAAPTPath(IAndroidTarget target) { - IAndroidTarget realTarget = null; - if (target == null) { - AndmoreLogger.warn(SdkUtils.class, "Trying to find a suitable aapt application to use"); //$NON-NLS-1$ - IAndroidTarget[] allTargets = Sdk.getCurrent().getTargets(); - if (allTargets.length > 0) { - realTarget = allTargets[0]; - } - } else { - realTarget = target; - } - - while ((realTarget != null) && !realTarget.isPlatform()) { - realTarget = realTarget.getParent(); - } - - if (realTarget == null) { - AndmoreLogger.warn(SdkUtils.class, "No aapt executable found: do you have an Android platform installed?"); //$NON-NLS-1$ - } - - return realTarget != null ? realTarget.getPath(IAndroidTarget.ANDROID_JAR) : null; - } - - /** - * Gets the path to the "adb" executable of the SDK - * - * @return - */ - public static String getAdbPath() { - return AndmoreAndroidPlugin.getOsAbsoluteAdb(); - } - - /** - * Reloads the recognized AVD list - */ - public static void reloadAvds() { - - try { - getVmManager().reloadAvds(NullSdkLogger.getLogger()); - } catch (Exception e) { - AndmoreLogger.error(SdkUtils.class, "Error while reloading AVDs"); //$NON-NLS-1$ - } - - } - - protected static class NullSdkLogger implements ILogger { - - private static NullSdkLogger logger; - - private NullSdkLogger() { - - } - - public static ILogger getLogger() { - if (logger == null) { - logger = new NullSdkLogger(); - } - return logger; - } - - @Override - public void error(Throwable arg0, String arg1, Object... arg2) { - - } - - @Override - public void info(String arg0, Object... arg1) { - - } - - @Override - public void verbose(String arg0, Object... arg1) { - - } - - @Override - public void warning(String arg0, Object... arg1) { - - } - - } - - /** - * Gets the VmManager object - */ - public static AvdManager getVmManager() { - AvdManager vmManager = null; - Sdk sdk = getCurrentSdk(); - if (sdk != null) { - vmManager = sdk.getAvdManager(); - } - - return vmManager; - } - - /** - * Gets all available Targets - */ - public static IAndroidTarget[] getAllTargets() { - IAndroidTarget[] allTargets = null; - Sdk sdk = getCurrentSdk(); - if (sdk != null) { - allTargets = sdk.getTargets(); - } - return allTargets; - } - - /** - * Gets a Target by name - * - * @param name - * the target name - */ - public static IAndroidTarget getTargetByName(String name) { - IAndroidTarget ret = null; - - if ((name != null) && (name.length() > 0)) { - IAndroidTarget[] allTargets = getAllTargets(); - - for (int i = 0; i < allTargets.length; i++) { - if (name.equals(allTargets[i].getName())) { - ret = allTargets[i]; - break; - } - } - } - - return ret; - } - - /** - * Gets all VMs - */ - public static AvdInfo[] getAllVms() { - AvdInfo[] allVmInfo = null; - AvdManager vmManager = getVmManager(); - if (vmManager != null) { - allVmInfo = vmManager.getAllAvds(); - } - return allVmInfo; - } - - /** - * Gets all valid VMs - */ - public static AvdInfo[] getAllValidVms() { - AvdInfo[] validVmInfo = null; - AvdManager vmManager = getVmManager(); - if (vmManager != null) { - validVmInfo = vmManager.getValidAvds(); - } - return validVmInfo; - } - - /** - * Gets the name of all VMs that are recognized by the configured SDK. - */ - public static Collection getAllVmNames() { - Collection vmNames = new LinkedList(); - for (AvdInfo vm : getAllVms()) { - vmNames.add(vm.getName()); - } - return vmNames; - } - - /** - * Gets the name of all VMs that are recognized by the configured SDK. - */ - public static Collection getAllValidVmNames() { - Collection vmNames = new LinkedList(); - AvdInfo[] allAvds = getAllValidVms(); - if (allAvds != null) { - for (AvdInfo vm : allAvds) { - vmNames.add(vm.getName()); - } - } - - return vmNames; - } - - /** - * Gets a skin name - * - * @param vmInfo - * the VM to get the skin - */ - public static String getSkin(AvdInfo vmInfo) { - String skin = ""; //$NON-NLS-1$ - File configFile = vmInfo.getConfigFile(); - Properties p = new Properties(); - InputStream configFileStream = null; - try { - configFileStream = new FileInputStream(configFile); - p.load(configFileStream); - skin = p.getProperty(EMU_CONFIG_SKIN_NAME_PROPERTY); - } catch (FileNotFoundException e) { - AndmoreLogger.error(SdkUtils.class, - "Error getting VM skin definition. Could not find file " + configFile.getAbsolutePath(), e); //$NON-NLS-1$ - } catch (IOException e) { - AndmoreLogger.error(SdkUtils.class, - "Error getting VM skin definition. Could not access file " + configFile.getAbsolutePath(), e); //$NON-NLS-1$ - } finally { - if (configFileStream != null) { - try { - configFileStream.close(); - } catch (IOException e) { - // nothing to do - } - } - } - - return skin; - } - - /** - * Gets a VM by name. - * - * @param vmName - * The VM name - */ - public static AvdInfo getValidVm(String vmName) { - AvdInfo vmInfo = null; - AvdManager vmManager = getVmManager(); - if (vmManager != null) { - vmInfo = vmManager.getAvd(vmName, true); - } - return vmInfo; - } - - /** - * Gets a VM by name. - * - * @param vmName - * The VM name - */ - public static AvdInfo getVm(String vmName) { - AvdInfo vmInfo = null; - AvdManager vmManager = getVmManager(); - if (vmManager != null) { - vmInfo = vmManager.getAvd(vmName, false); - } - return vmInfo; - } - - /** - * Creates a new VM instance. - * - * @param folder - * Folder where the VM files will be stored - * @param name - * VM Name - * @param target - * VM Target represented by the IAndroidTarget object - * @param skinName - * VM Skin name from the VM Target - * - * @throws CoreException - */ - public static AvdInfo createVm(String folder, String name, IAndroidTarget target, String abiType, String skinName, - String useSnapshot, String sdCard) throws CoreException - - { - AvdInfo vmInfo; - AvdManager vmManager = SdkUtils.getVmManager(); - - // get the abi type - if (abiType == null) { - abiType = SdkConstants.ABI_ARMEABI; - } - - /* - * public VmInfo createVm(String parentFolder, String name, - * IAndroidTarget target, String skinName, String sdcard, Map - * hardwareConfig) - */ - - // TODO: FIX ME commented out for now. - vmInfo = null; - // vmInfo = vmManager.createAvd(new File(folder), name, target, abiType, - // skinName, sdCard, null, Boolean.parseBoolean(useSnapshot), - // true, false, NullSdkLogger.getLogger()); - - if (vmInfo == null) { - String errMsg = NLS.bind(AndroidNLS.EXC_SdkUtils_CannotCreateTheVMInstance, name); - - IStatus status = new Status(IStatus.ERROR, AndmoreAndroidPlugin.PLUGIN_ID, errMsg); - throw new CoreException(status); - } - - return vmInfo; - } - - /** - * Deletes a VM instance. - * - * @param name - * VM Name - */ - public static void deleteVm(String name) { - - AvdManager vmManager = SdkUtils.getVmManager(); - AvdInfo avdToDelete = vmManager != null ? vmManager.getAvd(name, false) : null; - if (avdToDelete != null) { - try { - if ((avdToDelete.getIniFile() != null) && avdToDelete.getIniFile().exists()) { - avdToDelete.getIniFile().delete(); - } - String path = avdToDelete.getDataFolderPath(); - if (path != null) { - File avdDir = new File(path); - if (avdDir.exists()) { - FileUtil.deleteDirRecursively(avdDir); - } - } - vmManager.removeAvd(avdToDelete); - - } catch (Exception e) { - AndmoreLogger.error("Could not delete AVD: " + e.getMessage()); //$NON-NLS-1$ - } - } - - } - - /** - * Get the reference to the File that points to the filesystem location of - * the directory where the user data files of the VM with the given name are - * stored. - * - * @param vmName - * name of the VM whose userdata directory is to be retrieved. - * @return the File object that references the filesystem location of the - * directory where the userdata files of the given VM will be - * stored. Returns a null reference if SDK is not configured or if - * there is no VM with the given name. - */ - public static File getUserdataDir(String vmName) { - AvdInfo vminfo = SdkUtils.getValidVm(vmName); - File userdataDir = null; - - if (vminfo != null) { - String vmpath = vminfo.getDataFolderPath(); - userdataDir = new File(vmpath); - } - - return userdataDir; - } - - /** - * Get the reference to the File that points to the filesystem location - * where the user data file of the VM with the given name is. - * - * @param vmName - * name of the VM whose userdata file is to be retrieved. - * @return the File object that references the filesystem location where the - * userdata of the given VM should be. Returns a null reference if - * SDK is not configured or if there is no VM with the given name. - */ - public static File getUserdataFile(String vmName) { - File userdataDir = getUserdataDir(vmName); - File userdataFile = null; - - if (userdataDir != null) { - userdataFile = new File(userdataDir, USERIMAGE_FILENAME); - } - - return userdataFile; - } - - /** - * Get the reference to the Files that point to the filesystem location - * where the state data files of the VM with the given name are. - * - * @param vmName - * name of the VM whose state data files is to be retrieved. - * @return the File objects that reference the filesystem location where the - * state data files of the given VM should be. Returns a null - * reference if SDK is not configured or if there is no VM with the - * given name. - */ - public static List getStateDataFiles(String vmName) { - File userdataDir = getUserdataDir(vmName); - List stateDataFiles = null; - - if (userdataDir != null) { - stateDataFiles = new ArrayList(); - - for (int i = 0; i < STATEDATA_FILENAMES.length; i++) { - stateDataFiles.add(new File(userdataDir, STATEDATA_FILENAMES[i])); - } - } - - return stateDataFiles; - } - - /** - * Retrieves all sample applications from a target - * - * @param target - * The target - * @return all sample applications from a target - */ - public static Object[] getSamples(IAndroidTarget target) { - List samples = new ArrayList(); - File samplesFolder = new File(target.getPath(IAndroidTarget.SAMPLES)); - samples = findSamples(samplesFolder, target); - return samples.toArray(); - } - - /** - * Find the samples inside an specific directory (recursively) - * - * @param folder - * the folder that can contain samples - * @param target - * the target of the samples in the folder - * @return a list of samples - */ - private static List findSamples(File folder, IAndroidTarget target) { - - List samples = new ArrayList(); - - if (folder.exists() && folder.isDirectory()) { - for (File sampleFolder : folder.listFiles()) { - if (sampleFolder.isDirectory()) { - if (Sample.isSample(sampleFolder)) { - samples.add(new Sample(sampleFolder, target)); - } else { - samples.addAll(findSamples(sampleFolder, target)); - } - } - } - } - - return samples; - } - - /** - * Retrieves all targets for a given SDK - * - * @param sdk - * The sdk - * - * @return all targets for the given SDK - */ - public static Object[] getTargets(Sdk sdk) { - Object[] targets = null; - if (sdk != null) { - targets = sdk.getTargets(); - } - return targets; - } - - /** - * Associates a project to a target - * - * @param project - * The project - * @param target - * The target - */ - public static void associate(IProject project, IAndroidTarget target) { - try { - Sdk.getCurrent().initProject(project, target); - } catch (Exception e) { - AndmoreLogger.error(SdkUtils.class, "Error associating project " + project.getName() //$NON-NLS-1$ - + " with target " + target.getName()); //$NON-NLS-1$ - } - } - - /** - * Retrieves the target for a project - * - * @param project - * the project - * - * @return the target for the project - */ - public static IAndroidTarget getTarget(IProject project) { - IAndroidTarget target = null; - if (project != null) { - target = Sdk.getCurrent().getTarget(project); - } - return target; - } - - /** - * Retrieves the target for a project - * - * @param project - * the project - * - * @return the target for the project - */ - public static String getMinSdkVersion(IProject project) { - String minSdkVersion = ""; - try { - AndroidManifestFile androidManifestFile = AndroidProjectManifestFile.getFromProject(project); - UsesSDKNode usesSdkNode = (UsesSDKNode) androidManifestFile.getNode(AndroidManifestNode.NodeType.UsesSdk); - if (usesSdkNode != null) { - minSdkVersion = usesSdkNode.getMinSdkVersion(); - } - - } catch (AndroidException e) { - AndmoreLogger.error("Error getting min sdk version. " + e.getMessage()); - } catch (CoreException e) { - AndmoreLogger.error("Error getting min sdk version. " + e.getMessage()); - } - return minSdkVersion; - } - - /** - * Retrieves all Activity Actions for a project. - * - * @param project - * The project - * - * @return all Activity Actions for the project. - */ - public static String[] getActivityActions(IProject project) { - String[] attributeValues = new String[0]; - - if ((project != null) && project.isOpen()) { - IAndroidTarget target = SdkUtils.getTarget(project); - AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); - - if (targetData != null) { - attributeValues = targetData.getAttributeValues("action", "android:name", "activity"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - } - - return attributeValues; - } - - /** - * Retrieves all Service Actions for a project. - * - * @param project - * The project - * - * @return all Service Actions for the project. - */ - public static String[] getServiceActions(IProject project) { - String[] attributeValues = new String[0]; - - if ((project != null) && project.isOpen()) { - IAndroidTarget target = SdkUtils.getTarget(project); - AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); - - if (targetData != null) { - attributeValues = targetData.getAttributeValues("action", "android:name", "service"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - } - - return attributeValues; - } - - /** - * Retrieves all Broadcast Receiver Actions for a project. - * - * @param project - * The project - * - * @return all Broadcast Receiver Actions for the project. - */ - public static String[] getReceiverActions(IProject project) { - String[] attributeValues = new String[0]; - - if ((project != null) && project.isOpen()) { - IAndroidTarget target = SdkUtils.getTarget(project); - AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); - - if (targetData != null) { - attributeValues = targetData.getAttributeValues("action", "android:name", "receiver"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - } - - return attributeValues; - } - - /** - * Retrieves all Intent Filter Actions for a project. - * - * @param project - * The project - * - * @return all Intent Filter Actions for the project. - */ - public static String[] getIntentFilterCategories(IProject project) { - String[] attributeValues = new String[0]; - - if ((project != null) && project.isOpen()) { - IAndroidTarget target = SdkUtils.getTarget(project); - AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); - - if (targetData != null) { - attributeValues = targetData.getAttributeValues("category", "android:name"); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - return attributeValues; - } - - /** - * Get the api version number for a given project - * - * @param project - * : the project - * @return the api version number or 0 if some error occurs - */ - public static int getApiVersionNumberForProject(IProject project) { - int api = 0; - IAndroidTarget target = SdkUtils.getTarget(project); - if (target != null) { - AndroidVersion version = target.getVersion(); - if (version != null) { - api = version.getApiLevel(); - } - } - return api; - } - - public static String getTargetNameForProject(IProject project) { - IAndroidTarget target = getTarget(project); - return target != null ? target.getName() : ""; //$NON-NLS-1$ - } - - public static boolean isPlatformTarget(String avdName) { - IAndroidTarget target = getValidVm(avdName).getTarget(); - return target != null ? target.isPlatform() : false; - } - - public static boolean isProjectTargetAPlatform(IProject project) { - IAndroidTarget target = getTarget(project); - return target != null ? target.isPlatform() : false; - } - - public static boolean isPlatformTarget(IAndroidTarget target) { - return target != null ? target.isPlatform() : false; - } - - /** - * Retrieves the APK configurations of a project - * - * @param project - * the project - * @return the APK configurations - */ - public static Map getAPKConfigurationsForProject(IProject project) { - - Map apkConfigurations = null; - - if ((project != null) && project.isOpen()) { - Sdk.getCurrent(); - // This is not supported on ADT 14 preview so let's comment it for - // now. - // apkConfigurations = - // Sdk.getProjectState(project).getApkSettings().getLocaleFilters(); - apkConfigurations = new HashMap(0); - } - - return apkConfigurations; - - } - - public static String getBaseTarget(String name) { - IAndroidTarget target = getValidVm(name).getTarget(); - while (!target.isPlatform()) { - target = target.getParent(); - } - return target.getName(); - } - - /** - * Check if an SDK is an OPhone Sdk - * - * @return - */ - public static boolean isOphoneSDK() { - boolean result = false; - - // check if the folder contains the oms jar - FilenameFilter omsFilenameFilter = new FilenameFilter() { - @Override - public boolean accept(File arg0, String arg1) { - return arg1.equals(IAndroidConstants.OPHONE_JAR); - } - }; - - Sdk sdk = getCurrentSdk(); - IAndroidTarget[] targets = sdk.getTargets(); - for (IAndroidTarget target : targets) { - File folder = new File(target.getLocation()); - if (folder.list(omsFilenameFilter).length > 0) { - result = true; - break; - } - } - - return result; - } - - /** - * Check if an SDK is an JIL sdk - * - * @return - */ - public static boolean isJILSdk() { - boolean result = false; - - // check if the folder contains the oms jar - FilenameFilter jilFilenameFilter = new FilenameFilter() { - - @Override - public boolean accept(File arg0, String arg1) { - return arg1.equals(IAndroidConstants.JIL_JAR); - } - }; - - Sdk sdk = getCurrentSdk(); - if (sdk != null) { - IAndroidTarget[] targets = sdk.getTargets(); - for (IAndroidTarget target : targets) { - File folder = new File(target.getLocation()); - if (folder.list(jilFilenameFilter).length > 0) { - result = true; - break; - } - } - } - - return result; - } - - public static String getEmulatorWindowName(String avdName, int port) { - String windowName = ""; //$NON-NLS-1$ - if (isJILSdk()) { - windowName = "JIL Emulator (" + avdName + ":" + port + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } else if (isOphoneSDK()) { - windowName = "OPhone Emulator (" + avdName + ":" + port + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } else { - windowName = port + ":" + avdName; //$NON-NLS-1$ - } - return windowName; - } - - public static boolean isLibraryProject(IProject project) { - return Sdk.getProjectState(project) != null ? Sdk.getProjectState(project).isLibrary() : false; - } - - /** - * Returns all available permissions - * - * @return String array containing the available permissions - */ - public static String[] getIntentFilterPermissions(IProject project) { - String[] attributeValues = new String[0]; - - if ((project != null) && project.isOpen()) { - IAndroidTarget target = SdkUtils.getTarget(project); - AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); - - if (targetData != null) { - attributeValues = targetData.getAttributeValues("uses-permission", "android:name"); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - return attributeValues; - } - - /** - * Try to repair an AVD. Currently only avds with wrong image path are - * repariable. Display a message with the changes to the config.ini - * - * @param avdInfo - * @return Status ERROR if an IO exception occured. - */ - public static IStatus repairAvd(AvdInfo avdInfo) { - IStatus status = Status.OK_STATUS; - - AvdManager avdManager = Sdk.getCurrent().getAvdManager(); - Display display = PlatformUI.getWorkbench().getDisplay(); - ILogger log = new MessageBoxLog(String.format("Result of updating AVD '%s':", avdInfo.getName()), //$NON-NLS-1$ - display, false); - try { - avdManager.updateAvd(avdInfo, log); - // display the result - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(true); - } - SdkUtils.reloadAvds(); - - } catch (IOException e) { - status = new Status(IStatus.ERROR, AndroidPlugin.PLUGIN_ID, AndroidNLS.SdkUtils_COULD_NOT_REPAIR_AVD, e); - } - - return status; - } - - public static String getDefaultSkin(String targetName) { - IAndroidTarget target = getTargetByName(targetName); - target.getDefaultSkin().getName(); - return target != null ? target.getDefaultSkin().getName() : "HVGA"; - } - - /** - * Returns the full absolute OS path to a skin specified by name for a given - * target. - * - * @param skinName - * The name of the skin to find. Case-sensitive. - * @param target - * The target where to find the skin. - * @return a {@link File} that may or may not actually exist. - */ - public static File getSkinFolder(String skinName, IAndroidTarget target) { - String path = target.getPath(IAndroidTarget.SKINS); - File skin = new File(path, skinName); - - if (skin.exists() == false && target.isPlatform() == false) { - target = target.getParent(); - - path = target.getPath(IAndroidTarget.SKINS); - skin = new File(path, skinName); - } - - return skin; - } -} +/* + * Copyright (C) 2012 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 org.eclipse.andmore.android; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.eclipse.andmore.AndmoreAndroidPlugin; +import org.eclipse.andmore.android.common.IAndroidConstants; +import org.eclipse.andmore.android.common.exception.AndroidException; +import org.eclipse.andmore.android.common.log.AndmoreLogger; +import org.eclipse.andmore.android.common.utilities.FileUtil; +import org.eclipse.andmore.android.i18n.AndroidNLS; +import org.eclipse.andmore.android.manifest.AndroidProjectManifestFile; +import org.eclipse.andmore.android.model.manifest.AndroidManifestFile; +import org.eclipse.andmore.android.model.manifest.dom.AndroidManifestNode; +import org.eclipse.andmore.android.model.manifest.dom.UsesSDKNode; +import org.eclipse.andmore.internal.sdk.AndroidTargetData; +import org.eclipse.andmore.internal.sdk.Sdk; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; + +import com.android.SdkConstants; +import com.android.repository.io.FileOpUtils; +import com.android.repository.testframework.FakeProgressIndicator; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.AndroidSdkHandler; +import com.android.sdkuilib.widgets.MessageBoxLog; +import com.android.utils.ILogger; + +/** + * DESCRIPTION: This class provides utility methods related to the Android SDK.
+ * USAGE: See public methods + */ + +public class SdkUtils { + public static final int API_LEVEL_FOR_PLATFORM_VERSION_3_0_0 = 11; + + public static final String VM_CONFIG_FILENAME = "config.ini"; //$NON-NLS-1$ + + public static final String USERIMAGE_FILENAME = "userdata-qemu.img"; //$NON-NLS-1$ + + public static final String[] STATEDATA_FILENAMES = { "cache.img", "userdata.img", "emulator-user.ini" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + }; + + public static final String EMU_CONFIG_SKIN_NAME_PROPERTY = "skin.name"; //$NON-NLS-1$ + + /** + * Gets the current SDK object + */ + public static Sdk getCurrentSdk() { + return Sdk.getCurrent(); + } + + /** + * Gets the directory where the configured SDK is located + */ + public static String getSdkPath() { + String sdkDir = null; + Sdk sdk = getCurrentSdk(); + if (sdk != null) { + sdkDir = sdk.getSdkFileLocation().getAbsolutePath(); + } + return sdkDir; + } + + /** + * Gets the path to the "tools" folder of the SDK + * + * @return + */ + public static String getSdkToolsPath() { + return AndmoreAndroidPlugin.getOsSdkToolsFolder(); + } + + public static IAndroidTarget getTargetByAPILevel(Integer apiLevel) { + IAndroidTarget returnTarget = null; + + for (IAndroidTarget target : getAllTargets()) { + if (target.getVersion().getApiLevel() == apiLevel) { + returnTarget = target; + } + } + return returnTarget; + } + + /** + * Get the AAPT application path from an android target if null is passed, + * try to get some aapt + * + * @param target + * @return + */ + public static String getTargetAAPTPath(IAndroidTarget target) { + IAndroidTarget realTarget = null; + if (target == null) { + AndmoreLogger.warn(SdkUtils.class, "Trying to find a suitable aapt application to use"); //$NON-NLS-1$ + Collection allTargets = Sdk.getCurrent().getTargets(); + if (allTargets.size() > 0) { + realTarget = allTargets.iterator().next(); + } + } else { + realTarget = target; + } + + while ((realTarget != null) && !realTarget.isPlatform()) { + realTarget = realTarget.getParent(); + } + + if (realTarget == null) { + AndmoreLogger.warn(SdkUtils.class, "No aapt executable found: do you have an Android platform installed?"); //$NON-NLS-1$ + } + + return realTarget != null ? realTarget.getPath(IAndroidTarget.ANDROID_JAR) : null; + } + + /** + * Gets the path to the "adb" executable of the SDK + * + * @return + */ + public static String getAdbPath() { + return AndmoreAndroidPlugin.getOsAbsoluteAdb(); + } + + /** + * Reloads the recognized AVD list + */ + public static void reloadAvds() { + + try { + getVmManager().reloadAvds(NullSdkLogger.getLogger()); + } catch (Exception e) { + AndmoreLogger.error(SdkUtils.class, "Error while reloading AVDs"); //$NON-NLS-1$ + } + + } + + protected static class NullSdkLogger implements ILogger { + + private static NullSdkLogger logger; + + private NullSdkLogger() { + + } + + public static ILogger getLogger() { + if (logger == null) { + logger = new NullSdkLogger(); + } + return logger; + } + + @Override + public void error(Throwable arg0, String arg1, Object... arg2) { + + } + + @Override + public void info(String arg0, Object... arg1) { + + } + + @Override + public void verbose(String arg0, Object... arg1) { + + } + + @Override + public void warning(String arg0, Object... arg1) { + + } + + } + + /** + * Gets the VmManager object + */ + public static AvdManager getVmManager() { + AvdManager vmManager = null; + Sdk sdk = getCurrentSdk(); + if (sdk != null) { + vmManager = sdk.getAvdManager(); + } + + return vmManager; + } + + /** + * Gets all available Targets + */ + public static IAndroidTarget[] getAllTargets() { + IAndroidTarget[] allTargets = null; + Sdk sdk = getCurrentSdk(); + if (sdk != null) { + allTargets = sdk.getTargets().toArray(new IAndroidTarget[0]); + } + return allTargets; + } + + /** + * Gets a Target by name + * + * @param name + * the target name + */ + public static IAndroidTarget getTargetByName(String name) { + IAndroidTarget ret = null; + + if ((name != null) && (name.length() > 0)) { + IAndroidTarget[] allTargets = getAllTargets(); + + for (int i = 0; i < allTargets.length; i++) { + if (name.equals(allTargets[i].getName())) { + ret = allTargets[i]; + break; + } + } + } + + return ret; + } + + /** + * Gets all VMs + */ + public static AvdInfo[] getAllVms() { + AvdInfo[] allVmInfo = null; + AvdManager vmManager = getVmManager(); + if (vmManager != null) { + allVmInfo = vmManager.getAllAvds(); + } + return allVmInfo; + } + + /** + * Gets all valid VMs + */ + public static AvdInfo[] getAllValidVms() { + AvdInfo[] validVmInfo = null; + AvdManager vmManager = getVmManager(); + if (vmManager != null) { + validVmInfo = vmManager.getValidAvds(); + } + return validVmInfo; + } + + /** + * Gets the name of all VMs that are recognized by the configured SDK. + */ + public static Collection getAllVmNames() { + Collection vmNames = new LinkedList(); + for (AvdInfo vm : getAllVms()) { + vmNames.add(vm.getName()); + } + return vmNames; + } + + /** + * Gets the name of all VMs that are recognized by the configured SDK. + */ + public static Collection getAllValidVmNames() { + Collection vmNames = new LinkedList(); + AvdInfo[] allAvds = getAllValidVms(); + if (allAvds != null) { + for (AvdInfo vm : allAvds) { + vmNames.add(vm.getName()); + } + } + + return vmNames; + } + + /** + * Gets a skin name + * + * @param vmInfo + * the VM to get the skin + */ + public static String getSkin(AvdInfo vmInfo) { + String skin = ""; //$NON-NLS-1$ + File configFile = vmInfo.getConfigFile(); + Properties p = new Properties(); + InputStream configFileStream = null; + try { + configFileStream = new FileInputStream(configFile); + p.load(configFileStream); + skin = p.getProperty(EMU_CONFIG_SKIN_NAME_PROPERTY); + } catch (FileNotFoundException e) { + AndmoreLogger.error(SdkUtils.class, + "Error getting VM skin definition. Could not find file " + configFile.getAbsolutePath(), e); //$NON-NLS-1$ + } catch (IOException e) { + AndmoreLogger.error(SdkUtils.class, + "Error getting VM skin definition. Could not access file " + configFile.getAbsolutePath(), e); //$NON-NLS-1$ + } finally { + if (configFileStream != null) { + try { + configFileStream.close(); + } catch (IOException e) { + // nothing to do + } + } + } + + return skin; + } + + /** + * Gets a VM by name. + * + * @param vmName + * The VM name + */ + public static AvdInfo getValidVm(String vmName) { + AvdInfo vmInfo = null; + AvdManager vmManager = getVmManager(); + if (vmManager != null) { + vmInfo = vmManager.getAvd(vmName, true); + } + return vmInfo; + } + + /** + * Gets a VM by name. + * + * @param vmName + * The VM name + */ + public static AvdInfo getVm(String vmName) { + AvdInfo vmInfo = null; + AvdManager vmManager = getVmManager(); + if (vmManager != null) { + vmInfo = vmManager.getAvd(vmName, false); + } + return vmInfo; + } + + /** + * Creates a new VM instance. + * + * @param folder + * Folder where the VM files will be stored + * @param name + * VM Name + * @param target + * VM Target represented by the IAndroidTarget object + * @param skinName + * VM Skin name from the VM Target + * + * @throws CoreException + */ + public static AvdInfo createVm(String folder, String name, IAndroidTarget target, String abiType, String skinName, + String useSnapshot, String sdCard) throws CoreException + + { + AvdInfo vmInfo; + AvdManager vmManager = SdkUtils.getVmManager(); + + // get the abi type + if (abiType == null) { + abiType = SdkConstants.ABI_ARMEABI; + } + + /* + * public VmInfo createVm(String parentFolder, String name, + * IAndroidTarget target, String skinName, String sdcard, Map + * hardwareConfig) + */ + + // TODO: FIX ME commented out for now. + vmInfo = null; + // vmInfo = vmManager.createAvd(new File(folder), name, target, abiType, + // skinName, sdCard, null, Boolean.parseBoolean(useSnapshot), + // true, false, NullSdkLogger.getLogger()); + + if (vmInfo == null) { + String errMsg = NLS.bind(AndroidNLS.EXC_SdkUtils_CannotCreateTheVMInstance, name); + + IStatus status = new Status(IStatus.ERROR, AndmoreAndroidPlugin.PLUGIN_ID, errMsg); + throw new CoreException(status); + } + + return vmInfo; + } + + /** + * Deletes a VM instance. + * + * @param name + * VM Name + */ + public static void deleteVm(String name) { + + AvdManager vmManager = SdkUtils.getVmManager(); + AvdInfo avdToDelete = vmManager != null ? vmManager.getAvd(name, false) : null; + if (avdToDelete != null) { + try { + if ((avdToDelete.getIniFile() != null) && avdToDelete.getIniFile().exists()) { + avdToDelete.getIniFile().delete(); + } + String path = avdToDelete.getDataFolderPath(); + if (path != null) { + File avdDir = new File(path); + if (avdDir.exists()) { + FileUtil.deleteDirRecursively(avdDir); + } + } + vmManager.removeAvd(avdToDelete); + + } catch (Exception e) { + AndmoreLogger.error("Could not delete AVD: " + e.getMessage()); //$NON-NLS-1$ + } + } + + } + + /** + * Get the reference to the File that points to the filesystem location of + * the directory where the user data files of the VM with the given name are + * stored. + * + * @param vmName + * name of the VM whose userdata directory is to be retrieved. + * @return the File object that references the filesystem location of the + * directory where the userdata files of the given VM will be + * stored. Returns a null reference if SDK is not configured or if + * there is no VM with the given name. + */ + public static File getUserdataDir(String vmName) { + AvdInfo vminfo = SdkUtils.getValidVm(vmName); + File userdataDir = null; + + if (vminfo != null) { + String vmpath = vminfo.getDataFolderPath(); + userdataDir = new File(vmpath); + } + + return userdataDir; + } + + /** + * Get the reference to the File that points to the filesystem location + * where the user data file of the VM with the given name is. + * + * @param vmName + * name of the VM whose userdata file is to be retrieved. + * @return the File object that references the filesystem location where the + * userdata of the given VM should be. Returns a null reference if + * SDK is not configured or if there is no VM with the given name. + */ + public static File getUserdataFile(String vmName) { + File userdataDir = getUserdataDir(vmName); + File userdataFile = null; + + if (userdataDir != null) { + userdataFile = new File(userdataDir, USERIMAGE_FILENAME); + } + + return userdataFile; + } + + /** + * Get the reference to the Files that point to the filesystem location + * where the state data files of the VM with the given name are. + * + * @param vmName + * name of the VM whose state data files is to be retrieved. + * @return the File objects that reference the filesystem location where the + * state data files of the given VM should be. Returns a null + * reference if SDK is not configured or if there is no VM with the + * given name. + */ + public static List getStateDataFiles(String vmName) { + File userdataDir = getUserdataDir(vmName); + List stateDataFiles = null; + + if (userdataDir != null) { + stateDataFiles = new ArrayList(); + + for (int i = 0; i < STATEDATA_FILENAMES.length; i++) { + stateDataFiles.add(new File(userdataDir, STATEDATA_FILENAMES[i])); + } + } + + return stateDataFiles; + } + + /** + * Retrieves all sample applications from a target + * + * @param target + * The target + * @return all sample applications from a target + */ + public static Object[] getSamples(IAndroidTarget target) { + List samples = new ArrayList(); + File samplesFolder = new File(target.getPath(IAndroidTarget.SAMPLES)); + samples = findSamples(samplesFolder, target); + return samples.toArray(); + } + + /** + * Find the samples inside an specific directory (recursively) + * + * @param folder + * the folder that can contain samples + * @param target + * the target of the samples in the folder + * @return a list of samples + */ + private static List findSamples(File folder, IAndroidTarget target) { + + List samples = new ArrayList(); + + if (folder.exists() && folder.isDirectory()) { + for (File sampleFolder : folder.listFiles()) { + if (sampleFolder.isDirectory()) { + if (Sample.isSample(sampleFolder)) { + samples.add(new Sample(sampleFolder, target)); + } else { + samples.addAll(findSamples(sampleFolder, target)); + } + } + } + } + + return samples; + } + + /** + * Retrieves all targets for a given SDK + * + * @param sdk + * The sdk + * + * @return all targets for the given SDK + */ + public static Object[] getTargets(Sdk sdk) { + Object[] targets = null; + if (sdk != null) { + targets = sdk.getTargets().toArray(); + } + return targets; + } + + /** + * Associates a project to a target + * + * @param project + * The project + * @param target + * The target + */ + public static void associate(IProject project, IAndroidTarget target) { + try { + Sdk.getCurrent().initProject(project, target); + } catch (Exception e) { + AndmoreLogger.error(SdkUtils.class, "Error associating project " + project.getName() //$NON-NLS-1$ + + " with target " + target.getName()); //$NON-NLS-1$ + } + } + + /** + * Retrieves the target for a project + * + * @param project + * the project + * + * @return the target for the project + */ + public static IAndroidTarget getTarget(IProject project) { + IAndroidTarget target = null; + if (project != null) { + target = Sdk.getCurrent().getTarget(project); + } + return target; + } + + /** + * Retrieves the target for a project + * + * @param project + * the project + * + * @return the target for the project + */ + public static String getMinSdkVersion(IProject project) { + String minSdkVersion = ""; + try { + AndroidManifestFile androidManifestFile = AndroidProjectManifestFile.getFromProject(project); + UsesSDKNode usesSdkNode = (UsesSDKNode) androidManifestFile.getNode(AndroidManifestNode.NodeType.UsesSdk); + if (usesSdkNode != null) { + minSdkVersion = usesSdkNode.getMinSdkVersion(); + } + + } catch (AndroidException e) { + AndmoreLogger.error("Error getting min sdk version. " + e.getMessage()); + } catch (CoreException e) { + AndmoreLogger.error("Error getting min sdk version. " + e.getMessage()); + } + return minSdkVersion; + } + + /** + * Retrieves all Activity Actions for a project. + * + * @param project + * The project + * + * @return all Activity Actions for the project. + */ + public static String[] getActivityActions(IProject project) { + String[] attributeValues = new String[0]; + + if ((project != null) && project.isOpen()) { + IAndroidTarget target = SdkUtils.getTarget(project); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + + if (targetData != null) { + attributeValues = targetData.getAttributeValues("action", "android:name", "activity"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + + return attributeValues; + } + + /** + * Retrieves all Service Actions for a project. + * + * @param project + * The project + * + * @return all Service Actions for the project. + */ + public static String[] getServiceActions(IProject project) { + String[] attributeValues = new String[0]; + + if ((project != null) && project.isOpen()) { + IAndroidTarget target = SdkUtils.getTarget(project); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + + if (targetData != null) { + attributeValues = targetData.getAttributeValues("action", "android:name", "service"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + + return attributeValues; + } + + /** + * Retrieves all Broadcast Receiver Actions for a project. + * + * @param project + * The project + * + * @return all Broadcast Receiver Actions for the project. + */ + public static String[] getReceiverActions(IProject project) { + String[] attributeValues = new String[0]; + + if ((project != null) && project.isOpen()) { + IAndroidTarget target = SdkUtils.getTarget(project); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + + if (targetData != null) { + attributeValues = targetData.getAttributeValues("action", "android:name", "receiver"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + + return attributeValues; + } + + /** + * Retrieves all Intent Filter Actions for a project. + * + * @param project + * The project + * + * @return all Intent Filter Actions for the project. + */ + public static String[] getIntentFilterCategories(IProject project) { + String[] attributeValues = new String[0]; + + if ((project != null) && project.isOpen()) { + IAndroidTarget target = SdkUtils.getTarget(project); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + + if (targetData != null) { + attributeValues = targetData.getAttributeValues("category", "android:name"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + return attributeValues; + } + + /** + * Get the api version number for a given project + * + * @param project + * : the project + * @return the api version number or 0 if some error occurs + */ + public static int getApiVersionNumberForProject(IProject project) { + int api = 0; + IAndroidTarget target = SdkUtils.getTarget(project); + if (target != null) { + AndroidVersion version = target.getVersion(); + if (version != null) { + api = version.getApiLevel(); + } + } + return api; + } + + public static String getTargetNameForProject(IProject project) { + IAndroidTarget target = getTarget(project); + return target != null ? target.getName() : ""; //$NON-NLS-1$ + } + + public static boolean isPlatformTarget(String avdName) { + IAndroidTarget target = getCurrentSdk().getAndroidTargetFor(getValidVm(avdName)); + return target != null ? target.isPlatform() : false; + } + + public static boolean isProjectTargetAPlatform(IProject project) { + IAndroidTarget target = getTarget(project); + return target != null ? target.isPlatform() : false; + } + + public static boolean isPlatformTarget(IAndroidTarget target) { + return target != null ? target.isPlatform() : false; + } + + /** + * Retrieves the APK configurations of a project + * + * @param project + * the project + * @return the APK configurations + */ + public static Map getAPKConfigurationsForProject(IProject project) { + + Map apkConfigurations = null; + + if ((project != null) && project.isOpen()) { + Sdk.getCurrent(); + // This is not supported on ADT 14 preview so let's comment it for + // now. + // apkConfigurations = + // Sdk.getProjectState(project).getApkSettings().getLocaleFilters(); + apkConfigurations = new HashMap(0); + } + + return apkConfigurations; + + } + + public static String getBaseTarget(String name) { + IAndroidTarget target = getCurrentSdk().getAndroidTargetFor(getValidVm(name)); + while (!target.isPlatform()) { + target = target.getParent(); + } + return target.getName(); + } + + /** + * Check if an SDK is an OPhone Sdk + * + * @return + */ + public static boolean isOphoneSDK() { + boolean result = false; + + // check if the folder contains the oms jar + FilenameFilter omsFilenameFilter = new FilenameFilter() { + @Override + public boolean accept(File arg0, String arg1) { + return arg1.equals(IAndroidConstants.OPHONE_JAR); + } + }; + + for (IAndroidTarget target : getCurrentSdk().getTargets()) { + File folder = new File(target.getLocation()); + if (folder.list(omsFilenameFilter).length > 0) { + result = true; + break; + } + } + + return result; + } + + /** + * Check if an SDK is an JIL sdk + * + * @return + */ + public static boolean isJILSdk() { + boolean result = false; + + // check if the folder contains the oms jar + FilenameFilter jilFilenameFilter = new FilenameFilter() { + + @Override + public boolean accept(File arg0, String arg1) { + return arg1.equals(IAndroidConstants.JIL_JAR); + } + }; + + Sdk sdk = getCurrentSdk(); + if (sdk != null) { + for (IAndroidTarget target : sdk.getTargets()) { + File folder = new File(target.getLocation()); + if (folder.list(jilFilenameFilter).length > 0) { + result = true; + break; + } + } + } + + return result; + } + + public static String getEmulatorWindowName(String avdName, int port) { + String windowName = ""; //$NON-NLS-1$ + if (isJILSdk()) { + windowName = "JIL Emulator (" + avdName + ":" + port + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } else if (isOphoneSDK()) { + windowName = "OPhone Emulator (" + avdName + ":" + port + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } else { + windowName = port + ":" + avdName; //$NON-NLS-1$ + } + return windowName; + } + + public static boolean isLibraryProject(IProject project) { + return Sdk.getProjectState(project) != null ? Sdk.getProjectState(project).isLibrary() : false; + } + + /** + * Returns all available permissions + * + * @return String array containing the available permissions + */ + public static String[] getIntentFilterPermissions(IProject project) { + String[] attributeValues = new String[0]; + + if ((project != null) && project.isOpen()) { + IAndroidTarget target = SdkUtils.getTarget(project); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + + if (targetData != null) { + attributeValues = targetData.getAttributeValues("uses-permission", "android:name"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + return attributeValues; + } + + /** + * Try to repair an AVD. Currently only avds with wrong image path are + * repariable. Display a message with the changes to the config.ini + * + * @param avdInfo + * @return Status ERROR if an IO exception occured. + */ + public static IStatus repairAvd(AvdInfo avdInfo) { + IStatus status = Status.OK_STATUS; + + AvdManager avdManager = Sdk.getCurrent().getAvdManager(); + Display display = PlatformUI.getWorkbench().getDisplay(); + ILogger log = new MessageBoxLog(String.format("Result of updating AVD '%s':", avdInfo.getName()), //$NON-NLS-1$ + display, false); + try { + avdManager.updateAvd(avdInfo, avdInfo.getProperties()); + // display the result + if (log instanceof MessageBoxLog) { + ((MessageBoxLog) log).displayResult(true); + } + SdkUtils.reloadAvds(); + + } catch (IOException e) { + status = new Status(IStatus.ERROR, AndroidPlugin.PLUGIN_ID, AndroidNLS.SdkUtils_COULD_NOT_REPAIR_AVD, e); + } + + return status; + } + + public static String getDefaultSkin(String targetName) { + IAndroidTarget target = getTargetByName(targetName); + target.getDefaultSkin().getName(); + return target != null ? target.getDefaultSkin().getName() : "HVGA"; + } + + /** + * Returns the full absolute OS path to a skin specified by name for a given + * target. + * + * @param skinName + * The name of the skin to find. Case-sensitive. + * @param target + * The target where to find the skin. + * @return a {@link File} that may or may not actually exist. + */ + public static File getSkinFolder(String skinName, IAndroidTarget target) { + String path = target.getPath(IAndroidTarget.SKINS); + File skin = new File(path, skinName); + + if (skin.exists() == false && target.isPlatform() == false) { + target = target.getParent(); + + path = target.getPath(IAndroidTarget.SKINS); + skin = new File(path, skinName); + } + + return skin; + } +} diff --git a/andmore-core/plugins/android/src/org/eclipse/andmore/android/multidex/MultiDexManager.java b/andmore-core/plugins/android/src/org/eclipse/andmore/android/multidex/MultiDexManager.java index 3d730c24..0266e1ac 100644 --- a/andmore-core/plugins/android/src/org/eclipse/andmore/android/multidex/MultiDexManager.java +++ b/andmore-core/plugins/android/src/org/eclipse/andmore/android/multidex/MultiDexManager.java @@ -317,12 +317,12 @@ private static ProjectProperties getProjectProperties(IProject project) { String projectLocation = project.getLocation().toOSString(); // legacy support: look for default.properties - ProjectProperties properties = ProjectProperties.load(projectLocation, - PropertyType.LEGACY_DEFAULT); - if(properties == null) { - properties = ProjectProperties.load(projectLocation, PropertyType.PROJECT); - } + //ProjectProperties properties = ProjectProperties.load(projectLocation, + // PropertyType.LEGACY_DEFAULT); + //if(properties == null) { + // properties = ProjectProperties.load(projectLocation, PropertyType.PROJECT); + //} - return properties; + return ProjectProperties.load(projectLocation, PropertyType.PROJECT); } } diff --git a/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/elements/SdkTargetSelector.java b/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/elements/SdkTargetSelector.java index 9ebf898d..ec2a397f 100644 --- a/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/elements/SdkTargetSelector.java +++ b/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/elements/SdkTargetSelector.java @@ -1,316 +1,316 @@ -/* - * Copyright (C) 2012 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 org.eclipse.andmore.android.wizards.elements; - -import org.eclipse.andmore.android.AndroidPlugin; -import org.eclipse.andmore.android.SdkUtils; -import org.eclipse.andmore.android.i18n.AndroidNLS; -import org.eclipse.andmore.android.model.AndroidProject; -import org.eclipse.andmore.android.model.IWizardModel; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -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 com.android.sdklib.IAndroidTarget; - -/** - * SDK Selector for New Android Project Wizards - */ -public class SdkTargetSelector extends Composite { - private Table table; - - private Label mDescription; - - final private AndroidProject project; - - private IAndroidTarget selection = null; - - /** - * A selection listener that will check/uncheck items when they are - * double-clicked - */ - private final SelectionListener listener = new SelectionListener() { - /** Default selection means double-click on "most" platforms */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - i.setChecked(!i.getChecked()); - enforceSingleSelection(i); - updateDescription(i); - IAndroidTarget newSelection = getSelection(); - project.setSdkTarget(newSelection); - - if (newSelection != null) { - project.setMinSdkVersion(getSelection().getVersion().getApiString()); - } - notifyListeners(IWizardModel.MODIFIED, new Event()); - } - - } - - @Override - public void widgetSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - enforceSingleSelection(i); - updateDescription(i); - IAndroidTarget newSelection = getSelection(); - project.setSdkTarget(newSelection); - selection = newSelection; - project.setSample(null); - - /* - * if ((newSelection != null) && - * !selection.getFullName().equals(newSelection.getFullName())) - * { - * - * } - */ - - notifyListeners(IWizardModel.MODIFIED, new Event()); - } - - } - - /** - * If we're not in multiple selection mode, uncheck all other items when - * this one is selected. - */ - private void enforceSingleSelection(TableItem item) { - if (item.getChecked()) { - Table parentTable = item.getParent(); - for (TableItem i2 : parentTable.getItems()) { - if ((i2 != item) && i2.getChecked()) { - i2.setChecked(false); - } - } - } - } - }; - - /** - * Table Tool Tip Listener - */ - private final Listener toolTipListener = new Listener() { - @Override - public void handleEvent(Event event) { - switch (event.type) { - 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; - } - } - }; - - /** - * Creates a new SDK Target Selector. - * - * @param parent - * The parent composite where the selector will be added. - * @param project - * the android project - */ - public SdkTargetSelector(Composite parent, AndroidProject project) { - super(parent, SWT.NONE); - this.project = project; - - createContents(parent); - } - - /** - * Create Contents - * - * @param parent - */ - private void createContents(Composite parent) { - setLayout(new GridLayout()); - setLayoutData(new GridData(GridData.FILL_BOTH)); - setFont(parent.getFont()); - - table = new Table(this, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER); - table.setHeaderVisible(true); - table.setLinesVisible(false); - table.setLayoutData(new GridData(GridData.FILL_BOTH)); - - mDescription = new Label(this, SWT.WRAP); - mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - createColumns(table); - table.addSelectionListener(listener); - fillTable(); - setupTooltip(table); - } - - /** - * Create Table Columns - * - * @param table - */ - private void createColumns(final Table table) { - // create the table columns - final TableColumn nameColumn = new TableColumn(table, SWT.NONE); - nameColumn.setText(AndroidNLS.UI_SdkTargetSelector_SdkTargetNameColumn); - final TableColumn vendorColumn = new TableColumn(table, SWT.NONE); - vendorColumn.setText(AndroidNLS.UI_SdkTargetSelector_VendorNameColumn); - final TableColumn apiColumn = new TableColumn(table, SWT.NONE); - apiColumn.setText(AndroidNLS.UI_SdkTargetSelector_APILevelColumn); - final TableColumn sdkColumn = new TableColumn(table, SWT.NONE); - sdkColumn.setText(AndroidNLS.UI_SdkTargetSelector_SDKVersionColumn); - - table.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = table.getClientArea(); - nameColumn.setWidth((r.width * 25) / 100); // 25% - vendorColumn.setWidth((r.width * 50) / 100); // 50% - apiColumn.setWidth((r.width * 15) / 100); // 15% - sdkColumn.setWidth((r.width * 10) / 100); // 10% - } - }); - } - - /** - * Return table selection. - * - * @return - */ - protected IAndroidTarget getSelection() { - IAndroidTarget selectedItem = null; - for (TableItem item : table.getItems()) { - Object data = item.getData(); - if (item.getChecked() && (data instanceof IAndroidTarget)) { - selectedItem = (IAndroidTarget) data; - break; - } - } - return selectedItem; - } - - /** - * Fills the table with all SDK targets. - */ - private void fillTable() { - // get the targets from the sdk - IAndroidTarget[] targets = null; - if (SdkUtils.getCurrentSdk() != null) { - targets = SdkUtils.getAllTargets(); - } else { - final Runnable listener = new Runnable() { - @Override - public void run() { - table.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - table.removeAll(); - fillTable(); - AndroidPlugin.getDefault().removeSDKLoaderListener(this); - } - }); - } - }; - AndroidPlugin.getDefault().addSDKLoaderListener(listener); - table.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - AndroidPlugin.getDefault().removeSDKLoaderListener(listener); - } - }); - } - - if ((targets != null) && (targets.length > 0)) { - table.setEnabled(true); - for (IAndroidTarget target : targets) { - TableItem item = new TableItem(table, SWT.NONE); - item.setData(target); - item.setText(0, target.getName()); - item.setText(1, target.getVendor()); - item.setText(2, target.getVersion().getApiString()); - item.setText(3, target.getVersionName()); - if (target == project.getSdkTarget()) { - item.setChecked(true); - selection = target; - } - } - } else { - table.setEnabled(false); - TableItem item = new TableItem(table, SWT.NONE); - item.setData(null); - item.setText(0, AndroidNLS.UI_SdkTargetSelector_EmptyValue); - item.setText(1, AndroidNLS.UI_SdkTargetSelector_NoTargetAvailable); - item.setText(2, AndroidNLS.UI_SdkTargetSelector_EmptyValue); - item.setText(3, AndroidNLS.UI_SdkTargetSelector_EmptyValue); - } - } - - /** - * Add Tool tip for table - * - * @param table - */ - private void setupTooltip(final Table table) { - table.addListener(SWT.Dispose, toolTipListener); - table.addListener(SWT.MouseHover, toolTipListener); - table.addListener(SWT.MouseMove, toolTipListener); - table.addListener(SWT.KeyDown, toolTipListener); - } - - /** - * Updates the description label - */ - 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$ - } - } else { - mDescription.setText(""); - } - } - - @Override - public void setEnabled(boolean enabled) { - if (this.getEnabled() != enabled) { - table.setEnabled(enabled); - mDescription.setEnabled(enabled); - super.setEnabled(enabled); - } - } -} +/* + * Copyright (C) 2012 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 org.eclipse.andmore.android.wizards.elements; + +import org.eclipse.andmore.android.AndroidPlugin; +import org.eclipse.andmore.android.SdkUtils; +import org.eclipse.andmore.android.i18n.AndroidNLS; +import org.eclipse.andmore.android.model.AndroidProject; +import org.eclipse.andmore.android.model.IWizardModel; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +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 com.android.sdklib.IAndroidTarget; + +/** + * SDK Selector for New Android Project Wizards + */ +public class SdkTargetSelector extends Composite { + private Table table; + + private Label mDescription; + + final private AndroidProject project; + + private IAndroidTarget selection = null; + + /** + * A selection listener that will check/uncheck items when they are + * double-clicked + */ + private final SelectionListener listener = new SelectionListener() { + /** Default selection means double-click on "most" platforms */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + if (e.item instanceof TableItem) { + TableItem i = (TableItem) e.item; + i.setChecked(!i.getChecked()); + enforceSingleSelection(i); + updateDescription(i); + IAndroidTarget newSelection = getSelection(); + project.setSdkTarget(newSelection); + + if (newSelection != null) { + project.setMinSdkVersion(getSelection().getVersion().getApiString()); + } + notifyListeners(IWizardModel.MODIFIED, new Event()); + } + + } + + @Override + public void widgetSelected(SelectionEvent e) { + if (e.item instanceof TableItem) { + TableItem i = (TableItem) e.item; + enforceSingleSelection(i); + updateDescription(i); + IAndroidTarget newSelection = getSelection(); + project.setSdkTarget(newSelection); + selection = newSelection; + project.setSample(null); + + /* + * if ((newSelection != null) && + * !selection.getFullName().equals(newSelection.getFullName())) + * { + * + * } + */ + + notifyListeners(IWizardModel.MODIFIED, new Event()); + } + + } + + /** + * If we're not in multiple selection mode, uncheck all other items when + * this one is selected. + */ + private void enforceSingleSelection(TableItem item) { + if (item.getChecked()) { + Table parentTable = item.getParent(); + for (TableItem i2 : parentTable.getItems()) { + if ((i2 != item) && i2.getChecked()) { + i2.setChecked(false); + } + } + } + } + }; + + /** + * Table Tool Tip Listener + */ + private final Listener toolTipListener = new Listener() { + @Override + public void handleEvent(Event event) { + switch (event.type) { + 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; + } + } + }; + + /** + * Creates a new SDK Target Selector. + * + * @param parent + * The parent composite where the selector will be added. + * @param project + * the android project + */ + public SdkTargetSelector(Composite parent, AndroidProject project) { + super(parent, SWT.NONE); + this.project = project; + + createContents(parent); + } + + /** + * Create Contents + * + * @param parent + */ + private void createContents(Composite parent) { + setLayout(new GridLayout()); + setLayoutData(new GridData(GridData.FILL_BOTH)); + setFont(parent.getFont()); + + table = new Table(this, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER); + table.setHeaderVisible(true); + table.setLinesVisible(false); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + + mDescription = new Label(this, SWT.WRAP); + mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + createColumns(table); + table.addSelectionListener(listener); + fillTable(); + setupTooltip(table); + } + + /** + * Create Table Columns + * + * @param table + */ + private void createColumns(final Table table) { + // create the table columns + final TableColumn nameColumn = new TableColumn(table, SWT.NONE); + nameColumn.setText(AndroidNLS.UI_SdkTargetSelector_SdkTargetNameColumn); + final TableColumn vendorColumn = new TableColumn(table, SWT.NONE); + vendorColumn.setText(AndroidNLS.UI_SdkTargetSelector_VendorNameColumn); + final TableColumn apiColumn = new TableColumn(table, SWT.NONE); + apiColumn.setText(AndroidNLS.UI_SdkTargetSelector_APILevelColumn); + final TableColumn sdkColumn = new TableColumn(table, SWT.NONE); + sdkColumn.setText(AndroidNLS.UI_SdkTargetSelector_SDKVersionColumn); + + table.addControlListener(new ControlAdapter() { + @Override + public void controlResized(ControlEvent e) { + Rectangle r = table.getClientArea(); + nameColumn.setWidth((r.width * 25) / 100); // 25% + vendorColumn.setWidth((r.width * 50) / 100); // 50% + apiColumn.setWidth((r.width * 15) / 100); // 15% + sdkColumn.setWidth((r.width * 10) / 100); // 10% + } + }); + } + + /** + * Return table selection. + * + * @return + */ + protected IAndroidTarget getSelection() { + IAndroidTarget selectedItem = null; + for (TableItem item : table.getItems()) { + Object data = item.getData(); + if (item.getChecked() && (data instanceof IAndroidTarget)) { + selectedItem = (IAndroidTarget) data; + break; + } + } + return selectedItem; + } + + /** + * Fills the table with all SDK targets. + */ + private void fillTable() { + // get the targets from the sdk + IAndroidTarget[] targets = null; + if (SdkUtils.getCurrentSdk() != null) { + targets = SdkUtils.getAllTargets(); + } else { + final Runnable listener = new Runnable() { + @Override + public void run() { + table.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + table.removeAll(); + fillTable(); + AndroidPlugin.getDefault().removeSDKLoaderListener(this); + } + }); + } + }; + AndroidPlugin.getDefault().addSDKLoaderListener(listener); + table.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + AndroidPlugin.getDefault().removeSDKLoaderListener(listener); + } + }); + } + + if ((targets != null) && (targets.length > 0)) { + table.setEnabled(true); + for (IAndroidTarget target : targets) { + TableItem item = new TableItem(table, SWT.NONE); + item.setData(target); + item.setText(0, target.getName()); + item.setText(1, target.getVendor()); + item.setText(2, target.getVersion().getApiString()); + item.setText(3, target.getVersionName() == null ? target.getVersion().getApiString() : target.getVersionName()); + if (target == project.getSdkTarget()) { + item.setChecked(true); + selection = target; + } + } + } else { + table.setEnabled(false); + TableItem item = new TableItem(table, SWT.NONE); + item.setData(null); + item.setText(0, AndroidNLS.UI_SdkTargetSelector_EmptyValue); + item.setText(1, AndroidNLS.UI_SdkTargetSelector_NoTargetAvailable); + item.setText(2, AndroidNLS.UI_SdkTargetSelector_EmptyValue); + item.setText(3, AndroidNLS.UI_SdkTargetSelector_EmptyValue); + } + } + + /** + * Add Tool tip for table + * + * @param table + */ + private void setupTooltip(final Table table) { + table.addListener(SWT.Dispose, toolTipListener); + table.addListener(SWT.MouseHover, toolTipListener); + table.addListener(SWT.MouseMove, toolTipListener); + table.addListener(SWT.KeyDown, toolTipListener); + } + + /** + * Updates the description label + */ + 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$ + } + } else { + mDescription.setText(""); + } + } + + @Override + public void setEnabled(boolean enabled) { + if (this.getEnabled() != enabled) { + table.setEnabled(enabled); + mDescription.setEnabled(enabled); + super.setEnabled(enabled); + } + } +} diff --git a/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/project/TreeContentProvider.java b/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/project/TreeContentProvider.java index c7c57b9c..217cea1a 100644 --- a/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/project/TreeContentProvider.java +++ b/andmore-core/plugins/android/src/org/eclipse/andmore/android/wizards/project/TreeContentProvider.java @@ -1,129 +1,130 @@ -/* - * Copyright (C) 2012 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 org.eclipse.andmore.android.wizards.project; - -import org.eclipse.andmore.android.SdkUtils; -import org.eclipse.andmore.android.model.AndroidProject; -import org.eclipse.andmore.internal.sdk.Sdk; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -import com.android.sdklib.IAndroidTarget; - -/** - * Class that implements a content provider for the Samples Tree viewers. - */ -@SuppressWarnings("restriction") -class TreeContentProvider implements ITreeContentProvider { - AndroidProject project = null; - - public TreeContentProvider(AndroidProject project) { - this.project = project; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang. - * Object) - */ - @Override - public Object[] getChildren(Object arg0) { - Object[] objects; - - if (arg0 instanceof IAndroidTarget) { - objects = SdkUtils.getSamples((IAndroidTarget) arg0); - } else { - objects = new Object[0]; - } - return objects; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object - * ) - */ - @Override - public Object getParent(Object arg0) { - return null; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang. - * Object) - */ - @Override - public boolean hasChildren(Object arg0) { - Object[] obj = getChildren(arg0); - return obj == null ? false : obj.length > 0; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java - * .lang.Object) - */ - @Override - public Object[] getElements(Object arg0) { - Object[] objs = null; - - if (arg0 instanceof Sdk) { - Sdk sdk = (Sdk) arg0; - Object[] targets = SdkUtils.getTargets(sdk); - if (targets.length > 0) { - for (IAndroidTarget target : (IAndroidTarget[]) targets) { - if (target.equals(project.getSdkTarget())) { - objs = SdkUtils.getSamples(target); - } - } - } else { - objs = new Object[0]; - } - } - return objs; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.IContentProvider#dispose() - */ - @Override - public void dispose() { - // do nothing - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface - * .viewers.Viewer, java.lang.Object, java.lang.Object) - */ - @Override - public void inputChanged(Viewer arg0, Object arg1, Object arg2) { - // do nothing - } -} +/* + * Copyright (C) 2012 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 org.eclipse.andmore.android.wizards.project; + +import org.eclipse.andmore.android.SdkUtils; +import org.eclipse.andmore.android.model.AndroidProject; +import org.eclipse.andmore.internal.sdk.Sdk; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.android.sdklib.IAndroidTarget; + +/** + * Class that implements a content provider for the Samples Tree viewers. + */ +@SuppressWarnings("restriction") +class TreeContentProvider implements ITreeContentProvider { + AndroidProject project = null; + + public TreeContentProvider(AndroidProject project) { + this.project = project; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang. + * Object) + */ + @Override + public Object[] getChildren(Object arg0) { + Object[] objects; + + if (arg0 instanceof IAndroidTarget) { + objects = SdkUtils.getSamples((IAndroidTarget) arg0); + } else { + objects = new Object[0]; + } + return objects; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object + * ) + */ + @Override + public Object getParent(Object arg0) { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang. + * Object) + */ + @Override + public boolean hasChildren(Object arg0) { + Object[] obj = getChildren(arg0); + return obj == null ? false : obj.length > 0; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java + * .lang.Object) + */ + @Override + public Object[] getElements(Object arg0) { + Object[] objs = null; + + if (arg0 instanceof Sdk) { + Sdk sdk = (Sdk) arg0; + Object[] targets = SdkUtils.getTargets(sdk); + if (targets.length > 0) { + for (Object o : targets) { + IAndroidTarget target = (IAndroidTarget) o; + if (target.equals(project.getSdkTarget())) { + objs = SdkUtils.getSamples(target); + } + } + } else { + objs = new Object[0]; + } + } + return objs; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + @Override + public void dispose() { + // do nothing + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface + * .viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public void inputChanged(Viewer arg0, Object arg1, Object arg2) { + // do nothing + } +} diff --git a/andmore-core/plugins/certmanager/.classpath b/andmore-core/plugins/certmanager/.classpath index 21319ace..a6c5d251 100644 --- a/andmore-core/plugins/certmanager/.classpath +++ b/andmore-core/plugins/certmanager/.classpath @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/andmore-core/plugins/certmanager/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/certmanager/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/certmanager/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/certmanager/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/certmanager/META-INF/MANIFEST.MF b/andmore-core/plugins/certmanager/META-INF/MANIFEST.MF index c6ff8dd6..e3e12107 100644 --- a/andmore-core/plugins/certmanager/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/certmanager/META-INF/MANIFEST.MF @@ -1,32 +1,32 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.certmanager;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.certmanager.CertificateManagerActivator -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.andmore.android.common, - org.junit, - org.eclipse.equinox.security, - org.eclipse.core.resources, - org.eclipse.ui.ide, - org.eclipse.core.expressions -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Bundle-Localization: plugin -Bundle-ClassPath: ., - lib/bcprov-jdk15on-147.jar, - lib/bcpkix-jdk15on-147.jar -Import-Package: org.eclipse.ui.actions -Export-Package: org.eclipse.andmore.android.certmanager, - org.eclipse.andmore.android.certmanager.command, - org.eclipse.andmore.android.certmanager.core, - org.eclipse.andmore.android.certmanager.exception, - org.eclipse.andmore.android.certmanager.job, - org.eclipse.andmore.android.certmanager.packaging, - org.eclipse.andmore.android.certmanager.packaging.sign, - org.eclipse.andmore.android.certmanager.ui.model, - org.eclipse.andmore.android.certmanager.ui.wizards, - org.eclipse.andmore.android.certmanager.views +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.certmanager;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.certmanager.CertificateManagerActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.andmore.android.common, + org.junit, + org.eclipse.equinox.security, + org.eclipse.core.resources, + org.eclipse.ui.ide, + org.eclipse.core.expressions +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Bundle-ClassPath: ., + lib/bcprov-jdk15on-147.jar, + lib/bcpkix-jdk15on-147.jar +Import-Package: org.eclipse.ui.actions +Export-Package: org.eclipse.andmore.android.certmanager, + org.eclipse.andmore.android.certmanager.command, + org.eclipse.andmore.android.certmanager.core, + org.eclipse.andmore.android.certmanager.exception, + org.eclipse.andmore.android.certmanager.job, + org.eclipse.andmore.android.certmanager.packaging, + org.eclipse.andmore.android.certmanager.packaging.sign, + org.eclipse.andmore.android.certmanager.ui.model, + org.eclipse.andmore.android.certmanager.ui.wizards, + org.eclipse.andmore.android.certmanager.views diff --git a/andmore-core/plugins/common/.classpath b/andmore-core/plugins/common/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/common/.classpath +++ b/andmore-core/plugins/common/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/common/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/common/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/common/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/common/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/common/META-INF/MANIFEST.MF b/andmore-core/plugins/common/META-INF/MANIFEST.MF index b921b5a7..e0fed49d 100644 --- a/andmore-core/plugins/common/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/common/META-INF/MANIFEST.MF @@ -1,38 +1,38 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.common;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.common.CommonPlugin -Bundle-Vendor: %providerName -Bundle-Localization: plugin -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.ui.editors, - org.eclipse.ui.browser, - org.eclipse.text, - org.eclipse.andmore.android.logger, - org.eclipse.core.net, - org.eclipse.ui.net, - org.apache.xerces, - org.eclipse.jdt.core, - org.eclipse.ui.console, - org.eclipse.ui.ide, - org.apache.commons.httpclient -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: org.eclipse.andmore.android.common, - org.eclipse.andmore.android.common.exception, - org.eclipse.andmore.android.common.log, - org.eclipse.andmore.android.common.preferences, - org.eclipse.andmore.android.common.proxy, - org.eclipse.andmore.android.common.utilities, - org.eclipse.andmore.android.common.utilities.i18n, - org.eclipse.andmore.android.common.utilities.ui, - org.eclipse.andmore.android.manifest, - org.eclipse.andmore.android.model.manifest, - org.eclipse.andmore.android.model.manifest.dom, - org.eclipse.andmore.android.wizards, - org.eclipse.andmore.android.wizards.elements -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.common;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.common.CommonPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.ui.editors, + org.eclipse.ui.browser, + org.eclipse.text, + org.eclipse.andmore.android.logger, + org.eclipse.core.net, + org.eclipse.ui.net, + org.apache.xerces, + org.eclipse.jdt.core, + org.eclipse.ui.console, + org.eclipse.ui.ide, + org.apache.commons.httpclient +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Export-Package: org.eclipse.andmore.android.common, + org.eclipse.andmore.android.common.exception, + org.eclipse.andmore.android.common.log, + org.eclipse.andmore.android.common.preferences, + org.eclipse.andmore.android.common.proxy, + org.eclipse.andmore.android.common.utilities, + org.eclipse.andmore.android.common.utilities.i18n, + org.eclipse.andmore.android.common.utilities.ui, + org.eclipse.andmore.android.manifest, + org.eclipse.andmore.android.model.manifest, + org.eclipse.andmore.android.model.manifest.dom, + org.eclipse.andmore.android.wizards, + org.eclipse.andmore.android.wizards.elements +Bundle-ClassPath: . +Bundle-ActivationPolicy: lazy diff --git a/andmore-core/plugins/db.core/.classpath b/andmore-core/plugins/db.core/.classpath index 0b1bcf94..7498423d 100644 --- a/andmore-core/plugins/db.core/.classpath +++ b/andmore-core/plugins/db.core/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/db.core/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/db.core/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/db.core/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/db.core/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/db.core/META-INF/MANIFEST.MF b/andmore-core/plugins/db.core/META-INF/MANIFEST.MF index 41bcb242..01441043 100644 --- a/andmore-core/plugins/db.core/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/db.core/META-INF/MANIFEST.MF @@ -1,32 +1,32 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.db.core;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.db.core.DbCoreActivator -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.datatools.connectivity, - org.eclipse.andmore.android.common, - org.eclipse.core.resources, - org.eclipse.datatools.connectivity.sqm.core, - org.eclipse.datatools.modelbase.sql, - org.junit, - org.eclipse.datatools.sqltools.data.ui, - org.eclipse.andmore.android.codeutils, - org.eclipse.datatools.sqltools.editor.core, - org.eclipse.datatools.sqltools.result, - org.eclipse.core.expressions, - org.eclipse.datatools.sqltools.ddlgen.ui -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.db.core, - org.eclipse.andmore.android.db.core.command, - org.eclipse.andmore.android.db.core.event, - org.eclipse.andmore.android.db.core.exception, - org.eclipse.andmore.android.db.core.model, - org.eclipse.andmore.android.db.core.ui, - org.eclipse.andmore.android.db.core.ui.action, - org.eclipse.andmore.android.db.core.ui.view +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.db.core;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.db.core.DbCoreActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.datatools.connectivity, + org.eclipse.andmore.android.common, + org.eclipse.core.resources, + org.eclipse.datatools.connectivity.sqm.core, + org.eclipse.datatools.modelbase.sql, + org.junit, + org.eclipse.datatools.sqltools.data.ui, + org.eclipse.andmore.android.codeutils, + org.eclipse.datatools.sqltools.editor.core, + org.eclipse.datatools.sqltools.result, + org.eclipse.core.expressions, + org.eclipse.datatools.sqltools.ddlgen.ui +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.db.core, + org.eclipse.andmore.android.db.core.command, + org.eclipse.andmore.android.db.core.event, + org.eclipse.andmore.android.db.core.exception, + org.eclipse.andmore.android.db.core.model, + org.eclipse.andmore.android.db.core.ui, + org.eclipse.andmore.android.db.core.ui.action, + org.eclipse.andmore.android.db.core.ui.view diff --git a/andmore-core/plugins/db.devices/.classpath b/andmore-core/plugins/db.devices/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/db.devices/.classpath +++ b/andmore-core/plugins/db.devices/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/db.devices/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/db.devices/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/db.devices/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/db.devices/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/db.devices/META-INF/MANIFEST.MF b/andmore-core/plugins/db.devices/META-INF/MANIFEST.MF index fcd92cc9..675bb1ad 100644 --- a/andmore-core/plugins/db.devices/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/db.devices/META-INF/MANIFEST.MF @@ -1,22 +1,22 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.db.devices;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.db.devices.DbDevicesPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.andmore.android.db.core, - org.eclipse.andmore.android, - org.eclipse.jdt.core, - org.eclipse.datatools.modelbase.sql, - org.eclipse.andmore.android.common, - org.eclipse.ui.console, - org.eclipse.datatools.sqltools.result, - org.eclipse.sequoyah.device.framework, - org.eclipse.core.resources, - org.eclipse.andmore;bundle-version="0.5.0" -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Bundle-ActivationPolicy: lazy +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.db.devices;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.db.devices.DbDevicesPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.andmore.android.db.core, + org.eclipse.andmore.android, + org.eclipse.jdt.core, + org.eclipse.datatools.modelbase.sql, + org.eclipse.andmore.android.common, + org.eclipse.ui.console, + org.eclipse.datatools.sqltools.result, + org.eclipse.sequoyah.device.framework, + org.eclipse.core.resources, + org.eclipse.andmore;bundle-version="0.5.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy diff --git a/andmore-core/plugins/devices.services/.classpath b/andmore-core/plugins/devices.services/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/devices.services/.classpath +++ b/andmore-core/plugins/devices.services/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/devices.services/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/devices.services/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/devices.services/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/devices.services/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/devices.services/META-INF/MANIFEST.MF b/andmore-core/plugins/devices.services/META-INF/MANIFEST.MF index 01132bd3..92c2f994 100644 --- a/andmore-core/plugins/devices.services/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/devices.services/META-INF/MANIFEST.MF @@ -1,21 +1,21 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.devices.services;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.devices.services.DeviceServicesPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.andmore.android, - org.eclipse.andmore.android.handset, - org.eclipse.andmore.android.emulator, - org.eclipse.andmore.android.common, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.ui.console, - org.eclipse.ui, - org.eclipse.core.expressions, - org.eclipse.core.runtime -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.devices.services.i18n +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.devices.services;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.devices.services.DeviceServicesPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.andmore.android, + org.eclipse.andmore.android.handset, + org.eclipse.andmore.android.emulator, + org.eclipse.andmore.android.common, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.ui.console, + org.eclipse.ui, + org.eclipse.core.expressions, + org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.devices.services.i18n diff --git a/andmore-core/plugins/emulator/.classpath b/andmore-core/plugins/emulator/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/emulator/.classpath +++ b/andmore-core/plugins/emulator/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/emulator/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/emulator/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/emulator/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/emulator/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/emulator/META-INF/MANIFEST.MF b/andmore-core/plugins/emulator/META-INF/MANIFEST.MF index 7bfdee53..376e03f9 100644 --- a/andmore-core/plugins/emulator/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/emulator/META-INF/MANIFEST.MF @@ -1,47 +1,48 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.emulator;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.emulator.EmulatorPlugin -Bundle-Vendor: %providerName -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Require-Bundle: org.eclipse.andmore, - org.eclipse.andmore.ddms, - org.eclipse.andmore.android, - org.eclipse.andmore.android.common, - org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.core.net, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.framework.ui, - org.eclipse.sequoyah.device.framework.wizard, - org.eclipse.sequoyah.vnc.vncviewer, - org.eclipse.sequoyah.vnc.protocol, - org.eclipse.sequoyah.vnc.vncviewer.vncviews, - org.eclipse.andmore.base, - org.apache.commons.net;bundle-version="1.4.1", - org.apache.oro;bundle-version="2.0.8" -Export-Package: org.eclipse.andmore.android.emulator, - org.eclipse.andmore.android.emulator.core.devfrm, - org.eclipse.andmore.android.emulator.core.emulationui, - org.eclipse.andmore.android.emulator.core.exception, - org.eclipse.andmore.android.emulator.core.model, - org.eclipse.andmore.android.emulator.core.skin, - org.eclipse.andmore.android.emulator.core.utils, - org.eclipse.andmore.android.emulator.device, - org.eclipse.andmore.android.emulator.device.definition, - org.eclipse.andmore.android.emulator.device.handlers, - org.eclipse.andmore.android.emulator.device.instance, - org.eclipse.andmore.android.emulator.device.refresh, - org.eclipse.andmore.android.emulator.device.sync, - org.eclipse.andmore.android.emulator.i18n, - org.eclipse.andmore.android.emulator.logic, - org.eclipse.andmore.android.emulator.skin.android.parser, - org.eclipse.andmore.android.emulator.ui.view -Bundle-ClassPath: lib/jakarta-oro-2.0.8.jar, - . -Bundle-ActivationPolicy: lazy - +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.emulator;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.emulator.EmulatorPlugin +Bundle-Vendor: %providerName +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Require-Bundle: org.eclipse.andmore, + org.eclipse.andmore.ddms, + org.eclipse.andmore.android, + org.eclipse.andmore.android.common, + org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.net, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.framework.ui, + org.eclipse.sequoyah.device.framework.wizard, + org.eclipse.sequoyah.vnc.vncviewer, + org.eclipse.sequoyah.vnc.protocol, + org.eclipse.sequoyah.vnc.vncviewer.vncviews, + org.eclipse.andmore.swt, + org.apache.commons.net;bundle-version="1.4.1", + org.apache.oro;bundle-version="2.0.8", + org.eclipse.andmore.ddmuilib;bundle-version="0.5.2" +Export-Package: org.eclipse.andmore.android.emulator, + org.eclipse.andmore.android.emulator.core.devfrm, + org.eclipse.andmore.android.emulator.core.emulationui, + org.eclipse.andmore.android.emulator.core.exception, + org.eclipse.andmore.android.emulator.core.model, + org.eclipse.andmore.android.emulator.core.skin, + org.eclipse.andmore.android.emulator.core.utils, + org.eclipse.andmore.android.emulator.device, + org.eclipse.andmore.android.emulator.device.definition, + org.eclipse.andmore.android.emulator.device.handlers, + org.eclipse.andmore.android.emulator.device.instance, + org.eclipse.andmore.android.emulator.device.refresh, + org.eclipse.andmore.android.emulator.device.sync, + org.eclipse.andmore.android.emulator.i18n, + org.eclipse.andmore.android.emulator.logic, + org.eclipse.andmore.android.emulator.skin.android.parser, + org.eclipse.andmore.android.emulator.ui.view +Bundle-ClassPath: lib/jakarta-oro-2.0.8.jar, + . +Bundle-ActivationPolicy: lazy + diff --git a/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/instance/AndroidDeviceInstance.java b/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/instance/AndroidDeviceInstance.java index 89914bd4..3b360074 100644 --- a/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/instance/AndroidDeviceInstance.java +++ b/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/instance/AndroidDeviceInstance.java @@ -58,6 +58,7 @@ import com.android.sdklib.IAndroidTarget; import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.repository.targets.AndroidTargetManager; /** * DESCRIPTION: This class represents a Android Emulator instance @@ -366,7 +367,7 @@ public static void populateWithVMInfo(String instanceName, Properties instancePr if (vmInfo != null) { // VM target - instanceProperties.setProperty(IDevicePropertiesConstants.vmTarget, vmInfo.getTarget().getName()); + instanceProperties.setProperty(IDevicePropertiesConstants.vmTarget, SdkUtils.getCurrentSdk().getAndroidTargetFor(vmInfo).getName()); // ABI Type instanceProperties.setProperty(IDevicePropertiesConstants.abiType, vmInfo.getAbiType()); @@ -404,8 +405,8 @@ public File getSkinPath() { AvdInfo avdInfo = SdkUtils.getValidVm(getName()); if (avdInfo != null) { String skinPath = avdInfo.getProperties().get("skin.path"); - skinPath = SdkUtils.getCurrentSdk().getSdkOsLocation() + skinPath; - IAndroidTarget target = avdInfo.getTarget(); + skinPath = new File(SdkUtils.getCurrentSdk().getSdkFileLocation(), skinPath).getAbsolutePath(); + IAndroidTarget target = SdkUtils.getCurrentSdk().getAndroidTargetFor(avdInfo); File candidateFile = new File(skinPath); // If path specified on the skin does not exist, try to retrieve it // from the target. @@ -459,7 +460,7 @@ public IAndroidTarget getAndroidTarget() { IAndroidTarget result = null; AvdInfo avdInfo = SdkUtils.getValidVm(getName()); if (avdInfo != null) { - result = avdInfo.getTarget(); + result = SdkUtils.getCurrentSdk().getAndroidTargetFor(avdInfo); } return result; } diff --git a/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/ui/PropertiesMainComposite.java b/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/ui/PropertiesMainComposite.java index 2a98ed18..fcef847e 100644 --- a/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/ui/PropertiesMainComposite.java +++ b/andmore-core/plugins/emulator/src/org/eclipse/andmore/android/emulator/device/ui/PropertiesMainComposite.java @@ -31,6 +31,7 @@ import org.eclipse.andmore.android.emulator.device.IDevicePropertiesConstants; import org.eclipse.andmore.android.emulator.device.definition.AndroidEmuDefMgr; import org.eclipse.andmore.android.emulator.i18n.EmulatorNLS; +import org.eclipse.andmore.internal.sdk.Sdk; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.preference.IPreferenceNode; @@ -59,8 +60,12 @@ import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISystemImage; import com.android.SdkConstants; +import com.android.repository.testframework.FakeProgressIndicator; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.IdDisplay; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdklib.repository.targets.SystemImageManager; /** * DESCRIPTION:
@@ -818,18 +823,24 @@ public void modifyText(ModifyEvent e) { private void populateAbiTypeCombo(Combo abiTypeCombo) { // System Images represents the ABI types - ISystemImage[] images = vmTarget.getSystemImages(); + // TODO these IdDisplay are almost certainly wrong. + Collection images = Sdk.getCurrent().getAndroidSdkHandler().getSystemImageManager(new FakeProgressIndicator()) + .lookup(IdDisplay.create(vmTarget.getName(), vmTarget.getName()), vmTarget.getVersion(), + IdDisplay.create(vmTarget.getVendor(), vmTarget.getVendor())); // in case no images are found, get try its parent - if ((images == null) || ((images.length == 0) && !vmTarget.isPlatform())) { - images = vmTarget.getParent().getSystemImages(); + if ((images == null) || ((images.size() == 0) && !vmTarget.isPlatform())) { + IAndroidTarget parent = vmTarget.getParent(); + images = Sdk.getCurrent().getAndroidSdkHandler().getSystemImageManager(new FakeProgressIndicator()).lookup( + IdDisplay.create(parent.getName(), parent.getName()), parent.getVersion(), + IdDisplay.create(parent.getVendor(), parent.getVendor())); } // always clean abi combo since it will be reloaded abiTypeCombo.removeAll(); int i = 0; - if ((images != null) && (images.length > 0)) { + if ((images != null) && (images.size() > 0)) { for (ISystemImage image : images) { String prettyAbiName = AvdInfo.getPrettyAbiType(image); abiTypeCombo.add(prettyAbiName); diff --git a/andmore-core/plugins/handset/.classpath b/andmore-core/plugins/handset/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/handset/.classpath +++ b/andmore-core/plugins/handset/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/handset/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/handset/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/handset/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/handset/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/handset/META-INF/MANIFEST.MF b/andmore-core/plugins/handset/META-INF/MANIFEST.MF index e84a4485..3780d952 100644 --- a/andmore-core/plugins/handset/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/handset/META-INF/MANIFEST.MF @@ -1,20 +1,20 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.handset;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.handset.HandsetPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.andmore.android, - org.eclipse.andmore.android.common, - org.eclipse.ui, - org.eclipse.ui.console, - org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.common.utilities -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.handset, - org.eclipse.andmore.android.handset.i18n +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.handset;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.handset.HandsetPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.andmore.android, + org.eclipse.andmore.android.common, + org.eclipse.ui, + org.eclipse.ui.console, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.common.utilities +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.handset, + org.eclipse.andmore.android.handset.i18n diff --git a/andmore-core/plugins/installer/.classpath b/andmore-core/plugins/installer/.classpath index 0b1bcf94..7498423d 100644 --- a/andmore-core/plugins/installer/.classpath +++ b/andmore-core/plugins/installer/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/installer/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/installer/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/installer/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/installer/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/installer/META-INF/MANIFEST.MF b/andmore-core/plugins/installer/META-INF/MANIFEST.MF index b454b444..206ff52d 100644 --- a/andmore-core/plugins/installer/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/installer/META-INF/MANIFEST.MF @@ -1,40 +1,40 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.installer;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.installer.InstallerPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.equinox.p2.artifact.repository, - org.eclipse.equinox.p2.core, - org.eclipse.equinox.p2.engine, - org.eclipse.equinox.p2.metadata, - org.eclipse.equinox.p2.metadata.repository, - org.eclipse.equinox.p2.ui, - org.eclipse.equinox.p2.repository, - org.eclipse.equinox.p2.operations, - org.eclipse.equinox.p2.touchpoint.natives, - org.eclipse.andmore.android.common, - org.eclipse.jdt.launching, - org.eclipse.andmore, - org.apache.commons.httpclient, - org.eclipse.ui.browser, - org.eclipse.equinox.p2.ui.sdk, - org.eclipse.andmore.base -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.installer, - org.eclipse.andmore.android.installer.i18n, - org.eclipse.andmore.android.installer.ui.dialogs, - org.eclipse.andmore.android.installer.utilities -Import-Package: org.eclipse.andmore.android.installer.utilities, - org.eclipse.core.internal.net, - org.eclipse.core.net.proxy, - org.eclipse.equinox.security.storage, - org.eclipse.jdt.core, - org.eclipse.jdt.internal.ui, - org.eclipse.ui.internal.net.auth +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.installer;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.installer.InstallerPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.equinox.p2.artifact.repository, + org.eclipse.equinox.p2.core, + org.eclipse.equinox.p2.engine, + org.eclipse.equinox.p2.metadata, + org.eclipse.equinox.p2.metadata.repository, + org.eclipse.equinox.p2.ui, + org.eclipse.equinox.p2.repository, + org.eclipse.equinox.p2.operations, + org.eclipse.equinox.p2.touchpoint.natives, + org.eclipse.andmore.android.common, + org.eclipse.jdt.launching, + org.eclipse.andmore, + org.apache.commons.httpclient, + org.eclipse.ui.browser, + org.eclipse.equinox.p2.ui.sdk, + org.eclipse.andmore.base +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.installer, + org.eclipse.andmore.android.installer.i18n, + org.eclipse.andmore.android.installer.ui.dialogs, + org.eclipse.andmore.android.installer.utilities +Import-Package: org.eclipse.andmore.android.installer.utilities, + org.eclipse.core.internal.net, + org.eclipse.core.net.proxy, + org.eclipse.equinox.security.storage, + org.eclipse.jdt.core, + org.eclipse.jdt.internal.ui, + org.eclipse.ui.internal.net.auth diff --git a/andmore-core/plugins/launch/.classpath b/andmore-core/plugins/launch/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/launch/.classpath +++ b/andmore-core/plugins/launch/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/launch/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/launch/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/launch/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/launch/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/launch/META-INF/MANIFEST.MF b/andmore-core/plugins/launch/META-INF/MANIFEST.MF index e4746b8f..818eec6f 100644 --- a/andmore-core/plugins/launch/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/launch/META-INF/MANIFEST.MF @@ -1,25 +1,25 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.launch;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.launch.LaunchPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.andmore.android, - org.eclipse.andmore.android.emulator, - org.eclipse.andmore.android.common, - org.eclipse.debug.ui, - org.eclipse.jdt.launching, - org.eclipse.jdt.core, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.andmore.ddms, - org.eclipse.andmore, - org.eclipse.core.runtime, - org.eclipse.ui.console, - org.eclipse.ui, - org.eclipse.andmore.base -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.andmore.android.launch.i18n +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.launch;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.launch.LaunchPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.andmore.android, + org.eclipse.andmore.android.emulator, + org.eclipse.andmore.android.common, + org.eclipse.debug.ui, + org.eclipse.jdt.launching, + org.eclipse.jdt.core, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.andmore.ddms, + org.eclipse.andmore, + org.eclipse.core.runtime, + org.eclipse.ui.console, + org.eclipse.ui, + org.eclipse.andmore.swt +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.andmore.android.launch.i18n diff --git a/andmore-core/plugins/logger.collector/.classpath b/andmore-core/plugins/logger.collector/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/logger.collector/.classpath +++ b/andmore-core/plugins/logger.collector/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/logger.collector/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/logger.collector/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/logger.collector/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/logger.collector/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/logger.collector/META-INF/MANIFEST.MF b/andmore-core/plugins/logger.collector/META-INF/MANIFEST.MF index e66ba7f8..f2ffb600 100644 --- a/andmore-core/plugins/logger.collector/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/logger.collector/META-INF/MANIFEST.MF @@ -1,14 +1,14 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.logger.collector;singleton:=true -Bundle-Version: 0.5.2.qualifier -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime -Bundle-ActivationPolicy: lazy -Bundle-Vendor: %providerName -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.logger.collector.core -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: org.eclipse.andmore.android.common.utilities, - org.eclipse.andmore.android.logger +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.logger.collector;singleton:=true +Bundle-Version: 0.5.2.qualifier +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime +Bundle-ActivationPolicy: lazy +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.logger.collector.core +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: org.eclipse.andmore.android.common.utilities, + org.eclipse.andmore.android.logger diff --git a/andmore-core/plugins/logger/.classpath b/andmore-core/plugins/logger/.classpath index be9ef572..13f61b0e 100644 --- a/andmore-core/plugins/logger/.classpath +++ b/andmore-core/plugins/logger/.classpath @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/andmore-core/plugins/logger/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/logger/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/logger/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/logger/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/logger/META-INF/MANIFEST.MF b/andmore-core/plugins/logger/META-INF/MANIFEST.MF index 7feb2958..45349b74 100644 --- a/andmore-core/plugins/logger/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/logger/META-INF/MANIFEST.MF @@ -1,13 +1,13 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Andmore Android Logger -Bundle-SymbolicName: org.eclipse.andmore.android.logger;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.logger.internal.Activator -Bundle-Vendor: Eclipse Andmore -Export-Package: org.eclipse.andmore.android.logger -Bundle-ClassPath: lib/log4j-1.2.14.jar, - . -Require-Bundle: org.eclipse.core.runtime -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Andmore Android Logger +Bundle-SymbolicName: org.eclipse.andmore.android.logger;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.logger.internal.Activator +Bundle-Vendor: Eclipse Andmore +Export-Package: org.eclipse.andmore.android.logger +Bundle-ClassPath: lib/log4j-1.2.14.jar, + . +Require-Bundle: org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy diff --git a/andmore-core/plugins/mat/.classpath b/andmore-core/plugins/mat/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/mat/.classpath +++ b/andmore-core/plugins/mat/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/mat/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/mat/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/mat/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/mat/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/mat/META-INF/MANIFEST.MF b/andmore-core/plugins/mat/META-INF/MANIFEST.MF index cf28776a..9372c4b5 100644 --- a/andmore-core/plugins/mat/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/mat/META-INF/MANIFEST.MF @@ -1,21 +1,21 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.mat;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.mat.Activator -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.mat.ui, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.core.resources, - org.eclipse.andmore.android, - org.eclipse.andmore.android.emulator -Bundle-ActivationPolicy: lazy -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Export-Package: org.eclipse.andmore.android.mat.i18n -Import-Package: org.eclipse.andmore.android.common.log - +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.mat;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.mat.Activator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.mat.ui, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.core.resources, + org.eclipse.andmore.android, + org.eclipse.andmore.android.emulator +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Export-Package: org.eclipse.andmore.android.mat.i18n +Import-Package: org.eclipse.andmore.android.common.log + diff --git a/andmore-core/plugins/packaging.ui/.classpath b/andmore-core/plugins/packaging.ui/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/packaging.ui/.classpath +++ b/andmore-core/plugins/packaging.ui/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/packaging.ui/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/packaging.ui/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/packaging.ui/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/packaging.ui/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/packaging.ui/META-INF/MANIFEST.MF b/andmore-core/plugins/packaging.ui/META-INF/MANIFEST.MF index 4a497ac9..872ee7a3 100644 --- a/andmore-core/plugins/packaging.ui/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/packaging.ui/META-INF/MANIFEST.MF @@ -1,22 +1,22 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.packaging.ui;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.packaging.ui.PackagingUIPlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.core.resources, - org.eclipse.core.runtime, - org.eclipse.ui, - org.eclipse.ui.forms, - org.eclipse.ui.ide, - org.eclipse.ui.views, - org.eclipse.jdt.core, - org.eclipse.jdt.ui, - org.eclipse.andmore.android.common, - org.eclipse.andmore.android, - org.eclipse.andmore.android.certmanager -Bundle-Localization: plugin -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.andmore.android.packaging.ui.i18n +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.packaging.ui;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.packaging.ui.PackagingUIPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.resources, + org.eclipse.core.runtime, + org.eclipse.ui, + org.eclipse.ui.forms, + org.eclipse.ui.ide, + org.eclipse.ui.views, + org.eclipse.jdt.core, + org.eclipse.jdt.ui, + org.eclipse.andmore.android.common, + org.eclipse.andmore.android, + org.eclipse.andmore.android.certmanager +Bundle-Localization: plugin +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.andmore.android.packaging.ui.i18n diff --git a/andmore-core/plugins/remote.device/.classpath b/andmore-core/plugins/remote.device/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/remote.device/.classpath +++ b/andmore-core/plugins/remote.device/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/remote.device/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/remote.device/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/remote.device/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/remote.device/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/remote.device/META-INF/MANIFEST.MF b/andmore-core/plugins/remote.device/META-INF/MANIFEST.MF index dda83e9f..a13cc697 100644 --- a/andmore-core/plugins/remote.device/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/remote.device/META-INF/MANIFEST.MF @@ -1,20 +1,20 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.remote;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.android.remote.RemoteDevicePlugin -Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.sequoyah.device.framework, - org.eclipse.sequoyah.device.framework.ui, - org.eclipse.sequoyah.device.common.utilities, - org.eclipse.andmore.android.common, - org.eclipse.andmore.android -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-Localization: plugin -Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.andmore.android.remote, - org.eclipse.andmore.android.remote.i18n, - org.eclipse.andmore.android.remote.instance +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.remote;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.android.remote.RemoteDevicePlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.sequoyah.device.framework, + org.eclipse.sequoyah.device.framework.ui, + org.eclipse.sequoyah.device.common.utilities, + org.eclipse.andmore.android.common, + org.eclipse.andmore.android +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.andmore.android.remote, + org.eclipse.andmore.android.remote.i18n, + org.eclipse.andmore.android.remote.instance diff --git a/andmore-core/plugins/snippets/.classpath b/andmore-core/plugins/snippets/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/snippets/.classpath +++ b/andmore-core/plugins/snippets/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/snippets/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/snippets/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/snippets/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/snippets/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/snippets/META-INF/MANIFEST.MF b/andmore-core/plugins/snippets/META-INF/MANIFEST.MF index 3b9eddc8..47be168a 100644 --- a/andmore-core/plugins/snippets/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/snippets/META-INF/MANIFEST.MF @@ -1,19 +1,19 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.codesnippets;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Localization: plugin -Require-Bundle: org.eclipse.core.runtime, - org.eclipse.core.resources, - org.eclipse.ui, - org.eclipse.ui.ide, - org.eclipse.ui.editors, - org.eclipse.gef, - org.eclipse.jface.text, - org.eclipse.jdt.ui, - org.eclipse.wst.common.snippets, - org.eclipse.andmore.android.common -Bundle-Vendor: %providerName -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: org.eclipse.andmore.android.codesnippets.i18n +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.codesnippets;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Localization: plugin +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.ui, + org.eclipse.ui.ide, + org.eclipse.ui.editors, + org.eclipse.gef, + org.eclipse.jface.text, + org.eclipse.jdt.ui, + org.eclipse.wst.common.snippets, + org.eclipse.andmore.android.common +Bundle-Vendor: %providerName +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Export-Package: org.eclipse.andmore.android.codesnippets.i18n diff --git a/andmore-core/plugins/translation/.classpath b/andmore-core/plugins/translation/.classpath index c72d35a0..54f561c7 100644 --- a/andmore-core/plugins/translation/.classpath +++ b/andmore-core/plugins/translation/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/andmore-core/plugins/translation/.settings/org.eclipse.jdt.core.prefs b/andmore-core/plugins/translation/.settings/org.eclipse.jdt.core.prefs index c537b630..295926d9 100644 --- a/andmore-core/plugins/translation/.settings/org.eclipse.jdt.core.prefs +++ b/andmore-core/plugins/translation/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/andmore-core/plugins/translation/META-INF/MANIFEST.MF b/andmore-core/plugins/translation/META-INF/MANIFEST.MF index 7a4f1992..4e57a860 100644 --- a/andmore-core/plugins/translation/META-INF/MANIFEST.MF +++ b/andmore-core/plugins/translation/META-INF/MANIFEST.MF @@ -1,26 +1,26 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.android.translation;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: %providerName -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Require-Bundle: org.eclipse.core.net, - org.eclipse.core.runtime, - org.eclipse.jface, - org.eclipse.sequoyah.localization.tools, - org.eclipse.ui.workbench, - org.eclipse.andmore.android.common, - org.eclipse.ui.net, - org.eclipse.sequoyah.localization.android, - org.eclipse.sequoyah.localization.editor, - org.apache.commons.net;bundle-version="1.4.1", - org.apache.oro;bundle-version="2.0.8" -Bundle-ClassPath: . -Import-Package: org.apache.commons.httpclient, - org.apache.commons.httpclient.auth;version="3.1.0", - org.apache.commons.httpclient.methods;version="3.1.0", - org.apache.commons.httpclient.params;version="3.1.0" -Bundle-Activator: org.eclipse.andmore.android.localization.translators.TranslationPlugin -Bundle-Localization: plugin -Bundle-ActivationPolicy: lazy +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.android.translation;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: %providerName +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.net, + org.eclipse.core.runtime, + org.eclipse.jface, + org.eclipse.sequoyah.localization.tools, + org.eclipse.ui.workbench, + org.eclipse.andmore.android.common, + org.eclipse.ui.net, + org.eclipse.sequoyah.localization.android, + org.eclipse.sequoyah.localization.editor, + org.apache.commons.net;bundle-version="1.4.1", + org.apache.oro;bundle-version="2.0.8" +Bundle-ClassPath: . +Import-Package: org.apache.commons.httpclient, + org.apache.commons.httpclient.auth;version="3.1.0", + org.apache.commons.httpclient.methods;version="3.1.0", + org.apache.commons.httpclient.params;version="3.1.0" +Bundle-Activator: org.eclipse.andmore.android.localization.translators.TranslationPlugin +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/.classpath b/andmore-swt/org.eclipse.andmore.ddmuilib/.classpath index bb504db2..6042c676 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/.classpath +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/.classpath @@ -1,7 +1,6 @@ - diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/META-INF/MANIFEST.MF b/andmore-swt/org.eclipse.andmore.ddmuilib/META-INF/MANIFEST.MF index 412e670c..ebd3e520 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/META-INF/MANIFEST.MF +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/META-INF/MANIFEST.MF @@ -1,31 +1,32 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Localization: plugin -Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.andmore.ddmuilib;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: %Bundle-Vendor -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", - org.eclipse.equinox.common;bundle-version="3.8.0", - org.eclipse.jface;bundle-version="3.12.2", - org.eclipse.andmore.swt -Export-Package: com.android.ddmuilib, - com.android.ddmuilib.actions, - com.android.ddmuilib.annotation, - com.android.ddmuilib.console, - com.android.ddmuilib.explorer, - com.android.ddmuilib.handler, - com.android.ddmuilib.heap, - com.android.ddmuilib.location, - com.android.ddmuilib.log.event, - com.android.ddmuilib.logcat, - com.android.ddmuilib.net, - com.android.ddmuilib.screenrecord, - com.android.ddmuilib.vmtrace, - images -Bundle-ClassPath: ., - libs/chart_swt-1.0.13.jar, - libs/jcommon-1.0.24.jar, - libs/jfreechart-1.0.19.jar, - libs/jfreechart-swt-1.0.jar +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Localization: plugin +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.andmore.ddmuilib;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: %Bundle-Vendor +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", + org.eclipse.equinox.common;bundle-version="3.8.0", + org.eclipse.jface;bundle-version="3.12.2", + org.eclipse.andmore.swt, + org.eclipse.core.runtime;bundle-version="3.12.0" +Export-Package: com.android.ddmuilib, + com.android.ddmuilib.actions, + com.android.ddmuilib.annotation, + com.android.ddmuilib.console, + com.android.ddmuilib.explorer, + com.android.ddmuilib.handler, + com.android.ddmuilib.heap, + com.android.ddmuilib.location, + com.android.ddmuilib.log.event, + com.android.ddmuilib.logcat, + com.android.ddmuilib.net, + com.android.ddmuilib.screenrecord, + com.android.ddmuilib.vmtrace +Bundle-ClassPath: ., + libs/chart_swt-1.0.13.jar, + libs/jcommon-1.0.24.jar, + libs/jfreechart-1.0.19.jar, + libs/jfreechart-swt-1.0.jar +Import-Package: org.eclipse.ui.plugin diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/plugin.xml b/andmore-swt/org.eclipse.andmore.ddmuilib/plugin.xml new file mode 100644 index 00000000..b60f62ae --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/plugin.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/AllocationPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/AllocationPanel.java index 04a40405..04e09d46 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/AllocationPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/AllocationPanel.java @@ -22,7 +22,7 @@ import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; import com.android.ddmlib.Client; import com.android.ddmlib.ClientData.AllocationTrackingStatus; - +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; @@ -50,7 +50,6 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; @@ -94,6 +93,7 @@ public class AllocationPanel extends TablePanel { private Image mSortUpImg; private Image mSortDownImg; private String mFilterText = null; + private ImageFactory mImageFactory; /** * Content Provider to display the allocations of a client. @@ -184,6 +184,12 @@ public void removeListener(ILabelProviderListener listener) { } } + public AllocationPanel(ImageFactory imageFactory) + { + super(); + mImageFactory = imageFactory; + } + /** * Create our control(s). */ @@ -191,11 +197,9 @@ public void removeListener(ILabelProviderListener listener) { protected Control createControl(Composite parent) { final IPreferenceStore store = DdmUiPreferences.getStore(); - Display display = parent.getDisplay(); - // get some images - mSortUpImg = ImageLoader.getDdmUiLibLoader().loadImage("sort_up.png", display); - mSortDownImg = ImageLoader.getDdmUiLibLoader().loadImage("sort_down.png", display); + mSortUpImg = mImageFactory.getImageByName("sort_up.png"); + mSortDownImg = mImageFactory.getImageByName("sort_down.png"); // base composite for selected client with enabled thread update. mAllocationBase = new Composite(parent, SWT.NONE); diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/DevicePanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/DevicePanel.java index 992e0c03..71137146 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/DevicePanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/DevicePanel.java @@ -30,6 +30,7 @@ import com.android.ddmuilib.vmtrace.VmTraceOptionsDialog; import com.google.common.base.Throwables; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ILabelProviderListener; @@ -44,6 +45,7 @@ import org.eclipse.swt.SWTException; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; @@ -102,6 +104,7 @@ public final class DevicePanel extends Panel implements IDebugBridgeChangeListen private Image mWaitingImage; private Image mDebuggerImage; private Image mDebugErrorImage; + private ImageFactory mImageFactory; private final ArrayList mListeners = new ArrayList(); @@ -318,10 +321,12 @@ public interface IUiSelectionListener { /** * Creates the {@link DevicePanel} object. * @param advancedPortSupport if true the device panel will add support for selected client port + * @param imageFactory Image loader * and display the ports in the ui. */ - public DevicePanel(boolean advancedPortSupport) { + public DevicePanel(boolean advancedPortSupport, ImageFactory imageFactory) { mAdvancedPortSupport = advancedPortSupport; + mImageFactory = imageFactory; } public void addSelectionListener(IUiSelectionListener listener) { @@ -718,42 +723,68 @@ public void run() { } private void loadImages(Display display) { - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - if (mDeviceImage == null) { - mDeviceImage = loader.loadImage(display, "device.png", //$NON-NLS-1$ - ICON_WIDTH, ICON_WIDTH, - display.getSystemColor(SWT.COLOR_RED)); + String imageName = "device.png"; //$NON-NLS-1$ + mDeviceImage = mImageFactory.getImageByName(imageName); + if (mDeviceImage == null) { + mDeviceImage = loadImage(imageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_RED)); + } } if (mEmulatorImage == null) { - mEmulatorImage = loader.loadImage(display, - "emulator.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_BLUE)); + String imageName = "emulator.png"; //$NON-NLS-1$ + mEmulatorImage = mImageFactory.getImageByName(imageName); + if (mEmulatorImage == null) { + mEmulatorImage = loadImage(imageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_BLUE)); + } } if (mThreadImage == null) { - mThreadImage = loader.loadImage(display, ICON_THREAD, - ICON_WIDTH, ICON_WIDTH, - display.getSystemColor(SWT.COLOR_YELLOW)); + String imageName = ICON_THREAD; + mThreadImage = mImageFactory.getImageByName(imageName); + if (mThreadImage == null) { + mThreadImage = loadImage(imageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_YELLOW)); + } } if (mHeapImage == null) { - mHeapImage = loader.loadImage(display, ICON_HEAP, - ICON_WIDTH, ICON_WIDTH, - display.getSystemColor(SWT.COLOR_BLUE)); + String heapImageName = ICON_HEAP; + mHeapImage = mImageFactory.getImageByName(heapImageName); + if (mHeapImage == null) { + mHeapImage = loadImage(heapImageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_BLUE)); + } } if (mWaitingImage == null) { - mWaitingImage = loader.loadImage(display, - "debug-wait.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_RED)); + String waitImageName = "debug-wait.png"; //$NON-NLS-1$ + mWaitingImage = mImageFactory.getImageByName(waitImageName); + if (mWaitingImage == null) { + mWaitingImage = loadImage(waitImageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_RED)); + } } if (mDebuggerImage == null) { - mDebuggerImage = loader.loadImage(display, - "debug-attach.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_GREEN)); + String debugImageName = "debug-attach.png"; //$NON-NLS-1$ + mDebuggerImage = mImageFactory.getImageByName(debugImageName); + if (mDebuggerImage == null) { + mDebuggerImage = loadImage(debugImageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_GREEN)); + } } if (mDebugErrorImage == null) { - mDebugErrorImage = loader.loadImage(display, - "debug-error.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_RED)); + String deviceImageName = "device.png"; //$NON-NLS-1$ + mDebugErrorImage = mImageFactory.getImageByName(deviceImageName); + if (mDebugErrorImage == null) { + mDebugErrorImage = loadImage(deviceImageName, display, + ICON_WIDTH, ICON_WIDTH, + display.getSystemColor(SWT.COLOR_RED)); + } } } @@ -826,4 +857,8 @@ private void notifyListeners(IDevice selectedDevice, Client selectedClient) { } } + private Image loadImage(String imageName, Display display, int width, int height, Color color) { + return mImageFactory.getImageByName(imageName, new ReplacementImageFactory(display, width, height, color)); + } + } diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/EmulatorControlPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/EmulatorControlPanel.java index ce6f084d..c10ff3fb 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/EmulatorControlPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/EmulatorControlPanel.java @@ -32,6 +32,7 @@ import com.android.ddmuilib.location.WayPointContentProvider; import com.android.ddmuilib.location.WayPointLabelProvider; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ISelection; @@ -223,9 +224,11 @@ public void widgetSelected(SelectionEvent e) { }; private Composite mKmlPlayControls; private Composite mGpxPlayControls; + private ImageFactory mImageFactory; - public EmulatorControlPanel() { + public EmulatorControlPanel(ImageFactory imageFactory) { + mImageFactory = imageFactory; } /** @@ -535,9 +538,8 @@ private void createLocationControls(final Composite top) { createManualLocationControl(manualLocationComp); - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - mPlayImage = loader.loadImage("play.png", mParent.getDisplay()); //$NON-NLS-1$ - mPauseImage = loader.loadImage("pause.png", mParent.getDisplay()); //$NON-NLS-1$ + mPlayImage = mImageFactory.getImageByName("play.png"); //$NON-NLS-1$ + mPauseImage = mImageFactory.getImageByName("pause.png"); //$NON-NLS-1$ Composite gpxLocationComp = new Composite(mLocationFolders, SWT.NONE); item = new TabItem(mLocationFolders, SWT.NONE); @@ -836,14 +838,12 @@ public void widgetSelected(SelectionEvent e) { separator.setLayoutData(gd = new GridData( GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); gd.heightHint = 0; - - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); mGpxBackwardButton = new Button(mGpxPlayControls, SWT.TOGGLE | SWT.FLAT); - mGpxBackwardButton.setImage(loader.loadImage("backward.png", mParent.getDisplay())); //$NON-NLS-1$ + mGpxBackwardButton.setImage(mImageFactory.getImageByName("backward.png")); //$NON-NLS-1$ mGpxBackwardButton.setSelection(false); mGpxBackwardButton.addSelectionListener(mDirectionButtonAdapter); mGpxForwardButton = new Button(mGpxPlayControls, SWT.TOGGLE | SWT.FLAT); - mGpxForwardButton.setImage(loader.loadImage("forward.png", mParent.getDisplay())); //$NON-NLS-1$ + mGpxForwardButton.setImage(mImageFactory.getImageByName("forward.png")); //$NON-NLS-1$ mGpxForwardButton.setSelection(true); mGpxForwardButton.addSelectionListener(mDirectionButtonAdapter); @@ -976,13 +976,12 @@ public void widgetSelected(SelectionEvent e) { GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); gd.heightHint = 0; - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); mKmlBackwardButton = new Button(mKmlPlayControls, SWT.TOGGLE | SWT.FLAT); - mKmlBackwardButton.setImage(loader.loadImage("backward.png", mParent.getDisplay())); //$NON-NLS-1$ + mKmlBackwardButton.setImage(mImageFactory.getImageByName("backward.png")); //$NON-NLS-1$ mKmlBackwardButton.setSelection(false); mKmlBackwardButton.addSelectionListener(mDirectionButtonAdapter); mKmlForwardButton = new Button(mKmlPlayControls, SWT.TOGGLE | SWT.FLAT); - mKmlForwardButton.setImage(loader.loadImage("forward.png", mParent.getDisplay())); //$NON-NLS-1$ + mKmlForwardButton.setImage(mImageFactory.getImageByName("forward.png")); //$NON-NLS-1$ mKmlForwardButton.setSelection(true); mKmlForwardButton.addSelectionListener(mDirectionButtonAdapter); diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/HeapPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/HeapPanel.java index 8900570c..dcbbc7f9 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/HeapPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/HeapPanel.java @@ -382,9 +382,11 @@ public void widgetSelected(SelectionEvent e) { { mLinearHeapImage = new Label(mLinearBase, SWT.NONE); mLinearHeapImage.setLayoutData(new GridData()); - mLinearHeapImage.setImage(ImageLoader.createPlaceHolderArt(mDisplay, - PLACEHOLDER_LINEAR_H_SIZE, PLACEHOLDER_LINEAR_V_SIZE, - mDisplay.getSystemColor(SWT.COLOR_BLUE))); + ReplacementImageFactory replacementImageFactory = + new ReplacementImageFactory(mDisplay, + PLACEHOLDER_LINEAR_H_SIZE, PLACEHOLDER_LINEAR_V_SIZE, + mDisplay.getSystemColor(SWT.COLOR_BLUE)); + mLinearHeapImage.setImage(replacementImageFactory.getImage()); // create a composite to contain the bottom part (legend) Composite bottomSection = new Composite(mLinearBase, SWT.NONE); @@ -414,9 +416,11 @@ public void widgetSelected(SelectionEvent e) { if (DISPLAY_HILBERT_BITMAP) { mHilbertHeapImage = new Label(mHilbertBase, SWT.NONE); mHilbertHeapImage.setLayoutData(new GridData()); - mHilbertHeapImage.setImage(ImageLoader.createPlaceHolderArt(mDisplay, - PLACEHOLDER_HILBERT_SIZE, PLACEHOLDER_HILBERT_SIZE, - mDisplay.getSystemColor(SWT.COLOR_BLUE))); + ReplacementImageFactory replacementImageFactory = + new ReplacementImageFactory(mDisplay, + PLACEHOLDER_HILBERT_SIZE, PLACEHOLDER_HILBERT_SIZE, + mDisplay.getSystemColor(SWT.COLOR_BLUE)); + mHilbertHeapImage.setImage(replacementImageFactory.getImage()); // create a composite to contain the right part (legend + zoom) Composite rightSection = new Composite(mHilbertBase, SWT.NONE); diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ImageLoader.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ImageLoader.java deleted file mode 100644 index a6e31b40..00000000 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ImageLoader.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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.ddmuilib; - -import com.android.ddmlib.Log; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; - -import java.io.InputStream; -import java.net.URL; -import java.util.HashMap; - -/** - * Class to load images stored in a jar file. - * All images are loaded from /images/filename - * - * Because Java requires to know the jar file in which to load the image from, a class is required - * when getting the instance. Instances are cached and associated to the class passed to - * {@link #getLoader(Class)}. - * - * {@link #getDdmUiLibLoader()} use {@link ImageLoader#getClass()} as the class. This is to be used - * to load images from ddmuilib. - * - * Loaded images are stored so that 2 calls with the same filename will return the same object. - * This also means that {@link Image} object returned by the loader should never be disposed. - * - */ -public class ImageLoader { - - private static final String PATH = "/images/"; //$NON-NLS-1$ - - private final HashMap mLoadedImages = new HashMap(); - private static final HashMap, ImageLoader> mInstances = - new HashMap, ImageLoader>(); - private final Class mClass; - - /** - * Private constructor, creating an instance associated with a class. - * The class is used to identify which jar file the images are loaded from. - */ - private ImageLoader(Class theClass) { - if (theClass == null) { - theClass = ImageLoader.class; - } - mClass = theClass; - } - - /** - * Returns the {@link ImageLoader} instance to load images from ddmuilib.jar - */ - public static ImageLoader getDdmUiLibLoader() { - return getLoader(null); - } - - /** - * Returns an {@link ImageLoader} to load images based on a given class. - * - * The loader will load images from the jar from which the class was loaded. using - * {@link Class#getResource(String)} and {@link Class#getResourceAsStream(String)}. - * - * Since all images are loaded using the path /images/filename, any class from the - * jar will work. However since the loader is cached and reused when the query provides the same - * class instance, and since the loader will also cache the loaded images, it is recommended - * to always use the same class for a given Jar file. - * - */ - public static ImageLoader getLoader(Class theClass) { - ImageLoader instance = mInstances.get(theClass); - if (instance == null) { - instance = new ImageLoader(theClass); - mInstances.put(theClass, instance); - } - - return instance; - } - - /** - * Disposes all images for all instances. - * This should only be called when the program exits. - */ - public static void dispose() { - for (ImageLoader loader : mInstances.values()) { - loader.doDispose(); - } - } - - private synchronized void doDispose() { - for (Image image : mLoadedImages.values()) { - image.dispose(); - } - - mLoadedImages.clear(); - } - - /** - * Returns an {@link ImageDescriptor} for a given filename. - * - * This searches for an image located at /images/filename. - * - * @param filename the filename of the image to load. - */ - public ImageDescriptor loadDescriptor(String filename) { - URL url = mClass.getResource(PATH + filename); - // TODO cache in a map - return ImageDescriptor.createFromURL(url); - } - - /** - * Returns an {@link Image} for a given filename. - * - * This searches for an image located at /images/filename. - * - * @param filename the filename of the image to load. - * @param display the Display object - */ - public synchronized Image loadImage(String filename, Display display) { - Image img = mLoadedImages.get(filename); - if (img == null) { - String tmp = PATH + filename; - InputStream imageStream = mClass.getResourceAsStream(tmp); - - if (imageStream != null) { - img = new Image(display, imageStream); - mLoadedImages.put(filename, img); - } - - if (img == null) { - throw new RuntimeException("Failed to load " + tmp); - } - } - - return img; - } - - /** - * Loads an image from a resource. This method used a class to locate the - * resources, and then load the filename from /images inside the resources.
- * Extra parameters allows for creation of a replacement image of the - * loading failed. - * - * @param display the Display object - * @param fileName the file name - * @param width optional width to create replacement Image. If -1, null be - * be returned if the loading fails. - * @param height optional height to create replacement Image. If -1, null be - * be returned if the loading fails. - * @param phColor optional color to create replacement Image. If null, Blue - * color will be used. - * @return a new Image or null if the loading failed and the optional - * replacement size was -1 - */ - public Image loadImage(Display display, String fileName, int width, int height, - Color phColor) { - - Image img = loadImage(fileName, display); - - if (img == null) { - Log.w("ddms", "Couldn't load " + fileName); - // if we had the extra parameter to create replacement image then we - // create and return it. - if (width != -1 && height != -1) { - return createPlaceHolderArt(display, width, height, - phColor != null ? phColor : display - .getSystemColor(SWT.COLOR_BLUE)); - } - - // otherwise, just return null - return null; - } - - return img; - } - - /** - * Create place-holder art with the specified color. - */ - public static Image createPlaceHolderArt(Display display, int width, - int height, Color color) { - Image img = new Image(display, width, height); - GC gc = new GC(img); - gc.setForeground(color); - gc.drawLine(0, 0, width, height); - gc.drawLine(0, height - 1, width, -1); - gc.dispose(); - return img; - } -} diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ReplacementImageFactory.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ReplacementImageFactory.java new file mode 100644 index 00000000..63c50ca6 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ReplacementImageFactory.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 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.ddmuilib; + +import org.eclipse.andmore.base.resources.ImageFactory.ReplacementImager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.widgets.Display; + +public class ReplacementImageFactory implements ReplacementImager { + + private Display display; + private int width; + private int height; + private Color color; + + /** + * @param display Display object + * @param width Width to create replacement Image + * @param height Height to create replacement Image + * @param color Optional color to create replacement Image. If null, Blue + * color will be used. + */ + public ReplacementImageFactory(Display display, int width, int height, Color color) + { + this.display = display; + this.width = width; + this.height = height; + this.color = color != null ? color : display.getSystemColor(SWT.COLOR_BLUE); + } + + @Override + public ImageData create() { + Image img = getImage(); + ImageData imageData = img.getImageData(); + img.dispose(); + return imageData; + } + + public Image getImage() { + Image img = new Image(display, width, height); + GC gc = new GC(img); + gc.setForeground(color); + gc.drawLine(0, 0, width, height); + gc.drawLine(0, height - 1, width, -1); + gc.dispose(); + return img; + } + +} diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ScreenShotDialog.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ScreenShotDialog.java index fa49cc0e..8a379c1c 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ScreenShotDialog.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/ScreenShotDialog.java @@ -204,10 +204,9 @@ public void widgetSelected(SelectionEvent e) { data.horizontalSpan = colCount; mImageLabel.setLayoutData(data); Display display = shell.getDisplay(); - mImageLabel.setImage(ImageLoader.createPlaceHolderArt( - display, 50, 50, display.getSystemColor(SWT.COLOR_BLUE))); - - + ReplacementImageFactory replacementImageFactory = + new ReplacementImageFactory(display, 50, 50, display.getSystemColor(SWT.COLOR_BLUE)); + mImageLabel.setImage(replacementImageFactory.getImage()); shell.setDefaultButton(done); } @@ -244,9 +243,9 @@ private void updateImageDisplay(Shell shell) { Image image; if (mRawImage == null) { Display display = shell.getDisplay(); - image = ImageLoader.createPlaceHolderArt( - display, 320, 240, display.getSystemColor(SWT.COLOR_BLUE)); - + ReplacementImageFactory replacementImageFactory = + new ReplacementImageFactory(display, 320, 240, display.getSystemColor(SWT.COLOR_BLUE)); + image = replacementImageFactory.getImage(); mSave.setEnabled(false); mBusyLabel.setText("Screen not available"); } else { diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/explorer/DeviceExplorer.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/explorer/DeviceExplorer.java index cc602c4c..3781dbd5 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/explorer/DeviceExplorer.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/explorer/DeviceExplorer.java @@ -28,7 +28,6 @@ import com.android.ddmlib.SyncService.ISyncProgressMonitor; import com.android.ddmlib.TimeoutException; import com.android.ddmuilib.DdmUiPreferences; -import com.android.ddmuilib.ImageLoader; import com.android.ddmuilib.Panel; import com.android.ddmuilib.SyncProgressHelper; import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; @@ -36,6 +35,7 @@ import com.android.ddmuilib.actions.ICommonAction; import com.android.ddmuilib.console.DdmConsole; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; @@ -111,8 +111,10 @@ public class DeviceExplorer extends Panel { private IDevice mCurrentDevice; private String mDefaultSave; + private ImageFactory mImageFactory; - public DeviceExplorer() { + public DeviceExplorer(ImageFactory imageFactory) { + mImageFactory = imageFactory; } /** @@ -159,15 +161,14 @@ protected Control createControl(Composite parent) { mParent = parent; parent.setLayout(new FillLayout()); - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); if (mFileImage == null) { - mFileImage = loader.loadImage("file.png", mParent.getDisplay()); + mFileImage = mImageFactory.getImageByName("file.png"); } if (mFolderImage == null) { - mFolderImage = loader.loadImage("folder.png", mParent.getDisplay()); + mFolderImage = mImageFactory.getImageByName("folder.png"); } if (mPackageImage == null) { - mPackageImage = loader.loadImage("android.png", mParent.getDisplay()); + mPackageImage = mImageFactory.getImageByName("android.png"); } if (mOtherImage == null) { // TODO: find a default image for other. diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeHeapPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeHeapPanel.java index c845fc13..a11ef73b 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeHeapPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeHeapPanel.java @@ -25,9 +25,9 @@ import com.android.ddmuilib.BaseHeapPanel; import com.android.ddmuilib.ITableFocusListener; import com.android.ddmuilib.ITableFocusListener.IFocusedTableActivator; -import com.android.ddmuilib.ImageLoader; import com.android.ddmuilib.TableHelper; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.preference.IPreferenceStore; @@ -145,9 +145,11 @@ public class NativeHeapPanel extends BaseHeapPanel { private ToolItem mDiffsOnlyButton; private ToolItem mShowZygoteAllocationsButton; private ToolItem mExportHeapDataButton; + private ImageFactory mImageFactory; - public NativeHeapPanel(IPreferenceStore prefStore) { + public NativeHeapPanel(IPreferenceStore prefStore, ImageFactory imageFactory) { mPrefStore = prefStore; + mImageFactory = imageFactory; mPrefStore.setDefault(PREFS_SASH_HEIGHT_PERCENT, 75); mPrefStore.setDefault(PREFS_SYMBOL_SEARCH_PATH, ""); mPrefStore.setDefault(PREFS_GROUP_BY_LIBRARY, false); @@ -757,8 +759,7 @@ public void handleEvent(Event e) { private void initializeDetailsToolBar(ToolBar toolbar) { mGroupByButton = new ToolItem(toolbar, SWT.CHECK); - mGroupByButton.setImage(ImageLoader.getDdmUiLibLoader().loadImage(GROUPBY_IMAGE, - toolbar.getDisplay())); + mGroupByButton.setImage(mImageFactory.getImageByName(GROUPBY_IMAGE)); mGroupByButton.setToolTipText(TOOLTIP_GROUPBY); mGroupByButton.setSelection(mPrefStore.getBoolean(PREFS_GROUP_BY_LIBRARY)); mGroupByButton.addSelectionListener(new SelectionAdapter() { @@ -769,8 +770,7 @@ public void widgetSelected(SelectionEvent arg0) { }); mDiffsOnlyButton = new ToolItem(toolbar, SWT.CHECK); - mDiffsOnlyButton.setImage(ImageLoader.getDdmUiLibLoader().loadImage(DIFFS_ONLY_IMAGE, - toolbar.getDisplay())); + mDiffsOnlyButton.setImage(mImageFactory.getImageByName(DIFFS_ONLY_IMAGE)); mDiffsOnlyButton.setToolTipText(TOOLTIP_DIFFS_ONLY); mDiffsOnlyButton.setSelection(mPrefStore.getBoolean(PREFS_SHOW_DIFFS_ONLY)); mDiffsOnlyButton.addSelectionListener(new SelectionAdapter() { @@ -784,8 +784,7 @@ public void widgetSelected(SelectionEvent arg0) { }); mShowZygoteAllocationsButton = new ToolItem(toolbar, SWT.CHECK); - mShowZygoteAllocationsButton.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - ZYGOTE_IMAGE, toolbar.getDisplay())); + mShowZygoteAllocationsButton.setImage(mImageFactory.getImageByName(ZYGOTE_IMAGE)); mShowZygoteAllocationsButton.setToolTipText(TOOLTIP_ZYGOTE_ALLOCATIONS); mShowZygoteAllocationsButton.setSelection( mPrefStore.getBoolean(PREFS_SHOW_ZYGOTE_ALLOCATIONS)); @@ -797,8 +796,7 @@ public void widgetSelected(SelectionEvent arg0) { }); mExportHeapDataButton = new ToolItem(toolbar, SWT.PUSH); - mExportHeapDataButton.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - EXPORT_DATA_IMAGE, toolbar.getDisplay())); + mExportHeapDataButton.setImage(mImageFactory.getImageByName(EXPORT_DATA_IMAGE)); mExportHeapDataButton.setToolTipText(TOOLTIP_EXPORT_DATA); mExportHeapDataButton.addSelectionListener(new SelectionAdapter() { @Override diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventDisplayOptions.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventDisplayOptions.java index 33cdc0e9..a9e7addb 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventDisplayOptions.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventDisplayOptions.java @@ -20,10 +20,10 @@ import com.android.ddmlib.log.EventLogParser; import com.android.ddmlib.log.EventValueDescription; import com.android.ddmuilib.DdmUiPreferences; -import com.android.ddmuilib.ImageLoader; import com.android.ddmuilib.log.event.EventDisplay.OccurrenceDisplayDescriptor; import com.android.ddmuilib.log.event.EventDisplay.ValueDisplayDescriptor; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -112,9 +112,11 @@ private void setEnabled(boolean enable) { private boolean mProcessTextChanges = true; private Text mTimeLimitText; private Text mHistWidthText; + private ImageFactory mImageFactory; - EventDisplayOptions(Shell parent) { + EventDisplayOptions(Shell parent, ImageFactory imageFactory) { super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL); + mImageFactory = imageFactory; } /** @@ -273,10 +275,8 @@ public void widgetSelected(SelectionEvent e) { gl.verticalSpacing = 0; gl.horizontalSpacing = 0; - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); mEventDisplayNewButton = new Button(bottomControls, SWT.PUSH | SWT.FLAT); - mEventDisplayNewButton.setImage(loader.loadImage("add.png", //$NON-NLS-1$ - leftPanel.getDisplay())); + mEventDisplayNewButton.setImage(mImageFactory.getImageByName("add.png")); //$NON-NLS-1$ mEventDisplayNewButton.setToolTipText("Adds a new event display"); mEventDisplayNewButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER)); mEventDisplayNewButton.addSelectionListener(new SelectionAdapter() { @@ -287,8 +287,7 @@ public void widgetSelected(SelectionEvent e) { }); mEventDisplayDeleteButton = new Button(bottomControls, SWT.PUSH | SWT.FLAT); - mEventDisplayDeleteButton.setImage(loader.loadImage("delete.png", //$NON-NLS-1$ - leftPanel.getDisplay())); + mEventDisplayDeleteButton.setImage(mImageFactory.getImageByName("delete.png")); //$NON-NLS-1$ mEventDisplayDeleteButton.setToolTipText("Deletes the selected event display"); mEventDisplayDeleteButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER)); mEventDisplayDeleteButton.addSelectionListener(new SelectionAdapter() { @@ -299,8 +298,7 @@ public void widgetSelected(SelectionEvent e) { }); mEventDisplayUpButton = new Button(bottomControls, SWT.PUSH | SWT.FLAT); - mEventDisplayUpButton.setImage(loader.loadImage("up.png", //$NON-NLS-1$ - leftPanel.getDisplay())); + mEventDisplayUpButton.setImage(mImageFactory.getImageByName("up.png")); //$NON-NLS-1$ mEventDisplayUpButton.setToolTipText("Moves the selected event display up"); mEventDisplayUpButton.addSelectionListener(new SelectionAdapter() { @Override @@ -327,8 +325,7 @@ public void widgetSelected(SelectionEvent e) { }); mEventDisplayDownButton = new Button(bottomControls, SWT.PUSH | SWT.FLAT); - mEventDisplayDownButton.setImage(loader.loadImage("down.png", //$NON-NLS-1$ - leftPanel.getDisplay())); + mEventDisplayDownButton.setImage(mImageFactory.getImageByName("down.png")); //$NON-NLS-1$ mEventDisplayDownButton.setToolTipText("Moves the selected event display down"); mEventDisplayDownButton.addSelectionListener(new SelectionAdapter() { @Override diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventLogPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventLogPanel.java index 682971b5..28034760 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventLogPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/log/event/EventLogPanel.java @@ -32,6 +32,7 @@ import com.android.ddmuilib.annotation.WorkerThread; import com.android.ddmuilib.log.event.EventDisplay.ILogColumnListener; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; @@ -108,8 +109,11 @@ public class EventLogPanel extends TablePanel implements ILogListener, /** file containing the current log raw data. */ private File mTempFile = null; - public EventLogPanel() { + private ImageFactory mImageFactory; + + public EventLogPanel(ImageFactory imageFactory) { super(); + mImageFactory = imageFactory; mFormatter.setGroupingUsed(true); } @@ -204,7 +208,7 @@ public void run() { @UiThread public void openOptionPanel() { try { - EventDisplayOptions dialog = new EventDisplayOptions(mParent.getShell()); + EventDisplayOptions dialog = new EventDisplayOptions(mParent.getShell(), mImageFactory); if (dialog.open(mCurrentEventLogParser, mEventDisplays, mEvents)) { synchronized (mLock) { // get the new EventDisplay list diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/EditFilterDialog.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/EditFilterDialog.java index 1b3da726..ce9bc2fc 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/EditFilterDialog.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/EditFilterDialog.java @@ -16,8 +16,7 @@ package com.android.ddmuilib.logcat; -import com.android.ddmuilib.ImageLoader; - +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; @@ -74,13 +73,15 @@ public class EditFilterDialog extends Dialog { private Label mNameWarning; private Label mTagWarning; private Label mPidWarning; + private ImageFactory mImageFactory; - public EditFilterDialog(Shell parent) { + public EditFilterDialog(Shell parent, ImageFactory imageFactory) { super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL); + mImageFactory = imageFactory; } - public EditFilterDialog(Shell shell, LogFilter filter) { - this(shell); + public EditFilterDialog(Shell shell, ImageFactory imageFactory, LogFilter filter) { + this(shell, imageFactory); mFilter = filter; } @@ -180,8 +181,7 @@ public void modifyText(ModifyEvent e) { }); mNameWarning = new Label(nameComposite, SWT.NONE); - mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY, - mShell.getDisplay())); + mNameWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); // separator l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL); @@ -214,8 +214,7 @@ public void modifyText(ModifyEvent e) { }); mTagWarning = new Label(main, SWT.NONE); - mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY, - mShell.getDisplay())); + mTagWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); l = new Label(main, SWT.NONE); l.setText("by pid:"); @@ -239,8 +238,7 @@ public void modifyText(ModifyEvent e) { }); mPidWarning = new Label(main, SWT.NONE); - mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY, - mShell.getDisplay())); + mPidWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); l = new Label(main, SWT.NONE); l.setText("by Log level:"); @@ -341,19 +339,15 @@ private int getComboIndex(int logLevel) { private void validate() { boolean result = true; - + // then we check it only contains digits. if (mPid != null) { if (mPid.matches("[0-9]*") == false) { //$NON-NLS-1$ - mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_WARNING, - mShell.getDisplay())); + mPidWarning.setImage(mImageFactory.getImageByName(IMAGE_WARNING)); mPidWarning.setToolTipText("PID must be a number"); //$NON-NLS-1$ result = false; } else { - mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_EMPTY, - mShell.getDisplay())); + mPidWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); mPidWarning.setToolTipText(null); } } @@ -361,15 +355,11 @@ private void validate() { // then we check it not contains character | or : if (mTag != null) { if (mTag.matches(".*[:|].*") == true) { //$NON-NLS-1$ - mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_WARNING, - mShell.getDisplay())); + mTagWarning.setImage(mImageFactory.getImageByName(IMAGE_WARNING)); mTagWarning.setToolTipText("Tag cannot contain | or :"); //$NON-NLS-1$ result = false; } else { - mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_EMPTY, - mShell.getDisplay())); + mTagWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); mTagWarning.setToolTipText(null); } } @@ -377,15 +367,11 @@ private void validate() { // then we check it not contains character | or : if (mName != null && mName.length() > 0) { if (mName.matches(".*[:|].*") == true) { //$NON-NLS-1$ - mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_WARNING, - mShell.getDisplay())); + mNameWarning.setImage(mImageFactory.getImageByName(IMAGE_WARNING)); mNameWarning.setToolTipText("Name cannot contain | or :"); //$NON-NLS-1$ result = false; } else { - mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage( - IMAGE_EMPTY, - mShell.getDisplay())); + mNameWarning.setImage(mImageFactory.getImageByName(IMAGE_EMPTY)); mNameWarning.setToolTipText(null); } } else { diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogCatPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogCatPanel.java index 61c07dfd..02fa27b5 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogCatPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogCatPanel.java @@ -25,10 +25,10 @@ import com.android.ddmuilib.FindDialog; import com.android.ddmuilib.ITableFocusListener; import com.android.ddmuilib.ITableFocusListener.IFocusedTableActivator; -import com.android.ddmuilib.ImageLoader; import com.android.ddmuilib.SelectionDependentPanel; import com.android.ddmuilib.TableHelper; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.MessageDialog; @@ -208,12 +208,15 @@ public final class LogCatPanel extends SelectionDependentPanel // # of messages deleted since last refresh, synchronized on mLogBuffer private int mDeletedLogCount; + private ImageFactory mImageFactory; + /** * Construct a logcat panel. * @param prefStore preference store where UI preferences will be saved */ - public LogCatPanel(IPreferenceStore prefStore) { + public LogCatPanel(IPreferenceStore prefStore, ImageFactory imageFactory) { mPrefStore = prefStore; + mImageFactory = imageFactory; mLogBuffer = new ArrayList(LogCatMessageList.MAX_MESSAGES_DEFAULT); initializeFilters(); @@ -440,7 +443,7 @@ private void createFiltersToolbar(Composite parent) { /* new filter */ mNewFilterToolItem = new ToolItem(t, SWT.PUSH); mNewFilterToolItem.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_ADD_FILTER, t.getDisplay())); + mImageFactory.getImageByName(IMAGE_ADD_FILTER)); mNewFilterToolItem.setToolTipText("Add a new logcat filter"); mNewFilterToolItem.addSelectionListener(new SelectionAdapter() { @Override @@ -452,7 +455,7 @@ public void widgetSelected(SelectionEvent arg0) { /* delete filter */ mDeleteFilterToolItem = new ToolItem(t, SWT.PUSH); mDeleteFilterToolItem.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_DELETE_FILTER, t.getDisplay())); + mImageFactory.getImageByName(IMAGE_DELETE_FILTER)); mDeleteFilterToolItem.setToolTipText("Delete selected logcat filter"); mDeleteFilterToolItem.addSelectionListener(new SelectionAdapter() { @Override @@ -464,7 +467,7 @@ public void widgetSelected(SelectionEvent arg0) { /* edit filter */ mEditFilterToolItem = new ToolItem(t, SWT.PUSH); mEditFilterToolItem.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EDIT_FILTER, t.getDisplay())); + mImageFactory.getImageByName(IMAGE_EDIT_FILTER)); mEditFilterToolItem.setToolTipText("Edit selected logcat filter"); mEditFilterToolItem.addSelectionListener(new SelectionAdapter() { @Override @@ -671,8 +674,7 @@ public void widgetSelected(SelectionEvent arg0) { ToolBar toolBar = new ToolBar(c, SWT.FLAT); ToolItem saveToLog = new ToolItem(toolBar, SWT.PUSH); - saveToLog.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_SAVE_LOG_TO_FILE, - toolBar.getDisplay())); + saveToLog.setImage(mImageFactory.getImageByName(IMAGE_SAVE_LOG_TO_FILE)); saveToLog.setToolTipText("Export Selected Items To Text File.."); saveToLog.addSelectionListener(new SelectionAdapter() { @Override @@ -683,7 +685,7 @@ public void widgetSelected(SelectionEvent arg0) { ToolItem clearLog = new ToolItem(toolBar, SWT.PUSH); clearLog.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_CLEAR_LOG, toolBar.getDisplay())); + mImageFactory.getImageByName(IMAGE_CLEAR_LOG)); clearLog.setToolTipText("Clear Log"); clearLog.addSelectionListener(new SelectionAdapter() { @Override @@ -701,8 +703,7 @@ public void widgetSelected(SelectionEvent arg0) { final ToolItem showFiltersColumn = new ToolItem(toolBar, SWT.CHECK); showFiltersColumn.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_DISPLAY_FILTERS, - toolBar.getDisplay())); + mImageFactory.getImageByName(IMAGE_DISPLAY_FILTERS)); showFiltersColumn.setSelection(mPrefStore.getBoolean(DISPLAY_FILTERS_COLUMN_PREFKEY)); showFiltersColumn.setToolTipText("Display Saved Filters View"); showFiltersColumn.addSelectionListener(new SelectionAdapter() { @@ -716,8 +717,7 @@ public void widgetSelected(SelectionEvent event) { mScrollLockCheckBox = new ToolItem(toolBar, SWT.CHECK); mScrollLockCheckBox.setImage( - ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_SCROLL_LOCK, - toolBar.getDisplay())); + mImageFactory.getImageByName(IMAGE_SCROLL_LOCK)); mScrollLockCheckBox.setSelection(true); mScrollLockCheckBox.setToolTipText("Scroll Lock"); mScrollLockCheckBox.addSelectionListener(new SelectionAdapter() { diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogPanel.java b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogPanel.java index c4c6f8ab..207da3f6 100644 --- a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogPanel.java +++ b/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/com/android/ddmuilib/logcat/LogPanel.java @@ -30,6 +30,7 @@ import com.android.ddmuilib.TableHelper; import com.android.ddmuilib.actions.ICommonAction; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; @@ -197,6 +198,8 @@ protected static class LogMessageInfo { private LogCatViewInterface mLogCatViewInterface = null; + private ImageFactory mImageFactory; + /** message data, separated from content for multi line messages */ protected static class LogMessage { public LogMessageInfo data; @@ -332,10 +335,11 @@ public interface LogCatViewInterface { * @param mode The filtering mode */ public LogPanel(LogColors colors, - ILogFilterStorageManager filterStorage, int mode) { + ILogFilterStorageManager filterStorage, int mode, ImageFactory imageFactory) { mColors = colors; mFilterMode = mode; mFilterStorage = filterStorage; + mImageFactory = imageFactory; mStore = DdmUiPreferences.getStore(); } @@ -573,7 +577,7 @@ public void stopLogCat(boolean inUiThread) { * */ public void addFilter() { - EditFilterDialog dlg = new EditFilterDialog(mFolders.getShell()); + EditFilterDialog dlg = new EditFilterDialog(mFolders.getShell(), mImageFactory); if (dlg.open()) { synchronized (mBuffer) { // get the new filter in the array @@ -645,7 +649,7 @@ public void addFilter() { public void editFilter() { if (mCurrentFilter != null && mCurrentFilter != mDefaultFilter) { EditFilterDialog dlg = new EditFilterDialog( - mFolders.getShell(), mCurrentFilter); + mFolders.getShell(), mImageFactory, mCurrentFilter); if (dlg.open()) { synchronized (mBuffer) { // at this point the filter has been updated. diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/META-INF/MANIFEST.MF b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/META-INF/MANIFEST.MF index 8e2eace2..6e1641b1 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/META-INF/MANIFEST.MF +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/META-INF/MANIFEST.MF @@ -1,20 +1,22 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Localization: plugin -Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.andmore.hierarchyviewer2lib;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: %Bundle-Vendor -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", - org.eclipse.equinox.common;bundle-version="3.8.0", - org.eclipse.jface;bundle-version="3.12.2", - org.eclipse.andmore.swt, - org.eclipse.andmore.swtmenubar, - org.eclipse.andmore.ddmuilib -Export-Package: com.android.hierarchyviewerlib, - com.android.hierarchyviewerlib.actions, - com.android.hierarchyviewerlib.device, - com.android.hierarchyviewerlib.models, - com.android.hierarchyviewerlib.ui -Bundle-ClassPath: . +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Localization: plugin +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.andmore.hierarchyviewer2lib;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: %Bundle-Vendor +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", + org.eclipse.equinox.common;bundle-version="3.8.0", + org.eclipse.jface;bundle-version="3.12.2", + org.eclipse.andmore.swt, + org.eclipse.andmore.swtmenubar, + org.eclipse.andmore.ddmuilib, + org.eclipse.core.runtime;bundle-version="3.12.0" +Export-Package: com.android.hierarchyviewerlib, + com.android.hierarchyviewerlib.actions, + com.android.hierarchyviewerlib.device, + com.android.hierarchyviewerlib.models, + com.android.hierarchyviewerlib.ui +Bundle-ClassPath: . +Import-Package: org.eclipse.ui.plugin diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/plugin.xml b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/plugin.xml new file mode 100644 index 00000000..b60f62ae --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/plugin.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/HierarchyViewerDirector.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/HierarchyViewerDirector.java index ac4b5bb0..1a299ece 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/HierarchyViewerDirector.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/HierarchyViewerDirector.java @@ -38,6 +38,8 @@ import com.android.hierarchyviewerlib.ui.util.DrawableViewNode; import com.android.hierarchyviewerlib.ui.util.PsdFile; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.base.resources.JFaceImageLoader; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Image; @@ -68,6 +70,8 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener, } protected static HierarchyViewerDirector sDirector; + + private ImageFactory mImageFactory; public static final String TAG = "hierarchyviewer"; @@ -88,6 +92,10 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener, private static final Object mDevicesLock = new Object(); private Map mDevices = new HashMap(10); + public HierarchyViewerDirector(ImageFactory imageFactory) { + mImageFactory = imageFactory; + } + public static boolean isUsingDdmProtocol() { return sIsUsingDdmProtocol; } @@ -95,6 +103,7 @@ public static boolean isUsingDdmProtocol() { public void terminate() { WindowUpdater.terminate(); mPixelPerfectRefreshTimer.cancel(); + mImageFactory.dispose(); } public abstract String getAdbLocation(); @@ -788,4 +797,9 @@ public void setPixelPerfectAutoRefreshInterval(int value) { public int getPixelPerfectAutoRefreshInverval() { return mPixelPerfectAutoRefreshInterval; } + + public ImageFactory getImageFactory() { + return mImageFactory; + } + } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/CapturePSDAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/CapturePSDAction.java index 4331c7d1..cc74a096 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/CapturePSDAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/CapturePSDAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class CapturePSDAction extends TreeViewEnabledAction implements ImageAction { @@ -37,8 +36,8 @@ private CapturePSDAction(Shell shell) { super("&Capture Layers"); this.mShell = shell; setAccelerator(SWT.MOD1 + 'C'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("capture-psd.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("capture-psd.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Capture the window layers as a photoshop document"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DisplayViewAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DisplayViewAction.java index 00976583..c020e813 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DisplayViewAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DisplayViewAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class DisplayViewAction extends SelectedNodeEnabledAction implements ImageAction { @@ -37,8 +36,8 @@ private DisplayViewAction(Shell shell) { super("&Display View"); this.mShell = shell; setAccelerator(SWT.MOD1 + 'D'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("display.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("display.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Display the selected view image in a separate window"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DumpDisplayListAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DumpDisplayListAction.java index 2dc42b18..74372c88 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DumpDisplayListAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/DumpDisplayListAction.java @@ -16,12 +16,11 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class DumpDisplayListAction extends SelectedNodeEnabledAction implements ImageAction { @@ -31,8 +30,8 @@ public class DumpDisplayListAction extends SelectedNodeEnabledAction implements private DumpDisplayListAction() { super("Dump DisplayList"); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("load-view-hierarchy.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("load-view-hierarchy.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Request the view to output its displaylist to logcat"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/EvaluateContrastAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/EvaluateContrastAction.java index 1815bb9f..ad80a97b 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/EvaluateContrastAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/EvaluateContrastAction.java @@ -16,14 +16,11 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import org.eclipse.jface.action.Action; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class EvaluateContrastAction extends Action implements ImageAction { diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InspectScreenshotAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InspectScreenshotAction.java index 4ef1313a..71f857c2 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InspectScreenshotAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InspectScreenshotAction.java @@ -16,13 +16,13 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.device.IHvDevice; import com.android.hierarchyviewerlib.models.DeviceSelectionModel; import com.android.hierarchyviewerlib.models.DeviceSelectionModel.IWindowChangeListener; import com.android.hierarchyviewerlib.models.Window; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; @@ -38,8 +38,8 @@ public class InspectScreenshotAction extends Action implements ImageAction, IWin private InspectScreenshotAction() { super("Inspect &Screenshot"); setAccelerator(SWT.MOD1 + 'S'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("inspect-screenshot.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("inspect-screenshot.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Inspect a screenshot in the pixel perfect view"); setEnabled( diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InvalidateAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InvalidateAction.java index d3de05e9..a6e45552 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InvalidateAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/InvalidateAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class InvalidateAction extends SelectedNodeEnabledAction implements ImageAction { @@ -33,8 +32,8 @@ public class InvalidateAction extends SelectedNodeEnabledAction implements Image private InvalidateAction() { super("&Invalidate Layout"); setAccelerator(SWT.MOD1 + 'I'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("invalidate.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("invalidate.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Invalidate the layout for the current window"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadOverlayAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadOverlayAction.java index 4d25d657..1ced3c7f 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadOverlayAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadOverlayAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class LoadOverlayAction extends PixelPerfectEnabledAction implements ImageAction { @@ -37,8 +36,8 @@ private LoadOverlayAction(Shell shell) { super("Load &Overlay"); this.mShell = shell; setAccelerator(SWT.MOD1 + 'O'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("load-overlay.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("load-overlay.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Load an image to overlay the screenshot"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadViewHierarchyAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadViewHierarchyAction.java index 81a159c1..b1384d2d 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadViewHierarchyAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/LoadViewHierarchyAction.java @@ -16,13 +16,13 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.device.IHvDevice; import com.android.hierarchyviewerlib.models.DeviceSelectionModel; import com.android.hierarchyviewerlib.models.DeviceSelectionModel.IWindowChangeListener; import com.android.hierarchyviewerlib.models.Window; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; @@ -38,8 +38,8 @@ public class LoadViewHierarchyAction extends Action implements ImageAction, IWin private LoadViewHierarchyAction() { super("Load View &Hierarchy"); setAccelerator(SWT.MOD1 + 'H'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("load-view-hierarchy.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("load-view-hierarchy.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Load the view hierarchy into the tree view"); setEnabled( diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/PixelPerfectAutoRefreshAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/PixelPerfectAutoRefreshAction.java index 8f337c06..cd8f36d2 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/PixelPerfectAutoRefreshAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/PixelPerfectAutoRefreshAction.java @@ -16,14 +16,13 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class PixelPerfectAutoRefreshAction extends PixelPerfectEnabledAction implements ImageAction { @@ -34,8 +33,8 @@ public class PixelPerfectAutoRefreshAction extends PixelPerfectEnabledAction imp private PixelPerfectAutoRefreshAction() { super("Auto &Refresh", Action.AS_CHECK_BOX); setAccelerator(SWT.MOD1 + 'R'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("auto-refresh.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("auto-refresh.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Automatically refresh the screenshot"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/ProfileNodesAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/ProfileNodesAction.java index 79b08e2a..8e75d3f2 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/ProfileNodesAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/ProfileNodesAction.java @@ -16,12 +16,11 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class ProfileNodesAction extends SelectedNodeEnabledAction implements ImageAction { private static ProfileNodesAction sAction; @@ -30,8 +29,8 @@ public class ProfileNodesAction extends SelectedNodeEnabledAction implements Ima public ProfileNodesAction() { super("Profile Node"); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("profile.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("profile.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Obtain layout times for tree rooted at selected node"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectAction.java index 0c022857..c2edede8 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class RefreshPixelPerfectAction extends PixelPerfectEnabledAction implements ImageAction { @@ -33,8 +32,8 @@ public class RefreshPixelPerfectAction extends PixelPerfectEnabledAction impleme private RefreshPixelPerfectAction() { super("&Refresh Screenshot"); setAccelerator(SWT.F5); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("refresh-windows.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("refresh-windows.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Refresh the screenshot"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectTreeAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectTreeAction.java index 1823f480..bb1d5b18 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectTreeAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshPixelPerfectTreeAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class RefreshPixelPerfectTreeAction extends PixelPerfectEnabledAction implements ImageAction { @@ -33,8 +32,8 @@ public class RefreshPixelPerfectTreeAction extends PixelPerfectEnabledAction imp private RefreshPixelPerfectTreeAction() { super("Refresh &Tree"); setAccelerator(SWT.MOD1 + 'T'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("load-view-hierarchy.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("load-view-hierarchy.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Refresh the tree"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshViewAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshViewAction.java index e9b35e5a..2eb65783 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshViewAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshViewAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class RefreshViewAction extends TreeViewEnabledAction implements ImageAction { @@ -33,8 +32,8 @@ public class RefreshViewAction extends TreeViewEnabledAction implements ImageAct private RefreshViewAction() { super("Load View &Hierarchy"); setAccelerator(SWT.MOD1 + 'H'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("load-view-hierarchy.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("load-view-hierarchy.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Reload the view hierarchy"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshWindowsAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshWindowsAction.java index ae6754da..82c5237a 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshWindowsAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RefreshWindowsAction.java @@ -16,14 +16,13 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class RefreshWindowsAction extends Action implements ImageAction { @@ -34,8 +33,8 @@ public class RefreshWindowsAction extends Action implements ImageAction { private RefreshWindowsAction() { super("&Refresh"); setAccelerator(SWT.F5); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("refresh-windows.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("refresh-windows.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Refresh the list of devices"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RequestLayoutAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RequestLayoutAction.java index 7621a7c5..a15da7fd 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RequestLayoutAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/RequestLayoutAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; public class RequestLayoutAction extends SelectedNodeEnabledAction implements ImageAction { @@ -33,8 +32,8 @@ public class RequestLayoutAction extends SelectedNodeEnabledAction implements Im private RequestLayoutAction() { super("Request &Layout"); setAccelerator(SWT.MOD1 + 'L'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("request-layout.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("request-layout.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Request the view to lay out"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SavePixelPerfectAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SavePixelPerfectAction.java index 555ac5b4..1bcdc450 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SavePixelPerfectAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SavePixelPerfectAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class SavePixelPerfectAction extends PixelPerfectEnabledAction implements ImageAction { @@ -37,8 +36,8 @@ private SavePixelPerfectAction(Shell shell) { super("&Save as PNG"); this.mShell = shell; setAccelerator(SWT.MOD1 + 'S'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("save.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("save.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Save the screenshot as a PNG image"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SaveTreeViewAction.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SaveTreeViewAction.java index daefd309..c8c3a036 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SaveTreeViewAction.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/actions/SaveTreeViewAction.java @@ -16,13 +16,12 @@ package com.android.hierarchyviewerlib.actions; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class SaveTreeViewAction extends TreeViewEnabledAction implements ImageAction { @@ -37,8 +36,8 @@ private SaveTreeViewAction(Shell shell) { super("&Save as PNG"); this.mShell = shell; setAccelerator(SWT.MOD1 + 'S'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("save.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("save.png"); //$NON-NLS-1$ setImageDescriptor(ImageDescriptor.createFromImage(mImage)); setToolTipText("Save the tree view as a PNG image"); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/CaptureDisplay.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/CaptureDisplay.java index a3953fd3..67911dcc 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/CaptureDisplay.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/CaptureDisplay.java @@ -16,10 +16,10 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.models.ViewNode; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; @@ -121,8 +121,8 @@ private static void createShell() { sShell.addShellListener(sShellListener); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - Image image = imageLoader.loadImage("display.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + Image image = imageFactory.getImageByName("display.png"); //$NON-NLS-1$ sShell.setImage(image); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/DeviceSelector.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/DeviceSelector.java index 567f5dd6..116f5d4a 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/DeviceSelector.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/DeviceSelector.java @@ -16,13 +16,13 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.device.IHvDevice; import com.android.hierarchyviewerlib.models.DeviceSelectionModel; import com.android.hierarchyviewerlib.models.DeviceSelectionModel.IWindowChangeListener; import com.android.hierarchyviewerlib.models.Window; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; @@ -60,7 +60,7 @@ public class DeviceSelector extends Composite implements IWindowChangeListener, private Image mEmulatorImage; - private final static int ICON_WIDTH = 16; + // private final static int ICON_WIDTH = 16; private boolean mDoTreeViewStuff; @@ -203,14 +203,12 @@ public void loadResources() { } mBoldFont = new Font(Display.getDefault(), newFontData); - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); mDeviceImage = - loader.loadImage(display, "device.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$ - .getSystemColor(SWT.COLOR_RED)); + imageFactory.getImageByName("device.png"); mEmulatorImage = - loader.loadImage(display, "emulator.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$ - .getSystemColor(SWT.COLOR_BLUE)); + imageFactory.getImageByName("emulator.png"); } private DisposeListener mDisposeListener = new DisposeListener() { diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/EvaluateContrastDisplay.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/EvaluateContrastDisplay.java index 84170ed5..0d1b191d 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/EvaluateContrastDisplay.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/EvaluateContrastDisplay.java @@ -16,19 +16,17 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.models.EvaluateContrastModel; import com.android.hierarchyviewerlib.models.ViewNode; import com.android.hierarchyviewerlib.models.EvaluateContrastModel.ContrastResult; import com.android.hierarchyviewerlib.models.ViewNode.Property; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.GC; @@ -39,14 +37,11 @@ import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Shell; @@ -106,10 +101,10 @@ public class EvaluateContrastDisplay { sImageForColor = new HashMap(); sViewNodeForTreeItem = new HashMap(); - ImageLoader loader = ImageLoader.getLoader(EvaluateContrastDisplay.class); - sYellowImage = loader.loadImage("yellow.png", Display.getDefault()); - sRedImage = loader.loadImage("red.png", Display.getDefault()); - sGreenImage = loader.loadImage("green.png", Display.getDefault()); + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + sYellowImage = imageFactory.getImageByName("yellow.png"); + sRedImage = imageFactory.getImageByName("red.png"); + sGreenImage = imageFactory.getImageByName("green.png"); sRectangleForViewNode = new HashMap(); sBorderColorForViewNode = new HashMap(); diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java index 769fc013..a73f900f 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java @@ -16,11 +16,12 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; +import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.models.PixelPerfectModel; import com.android.hierarchyviewerlib.models.ViewNode; import com.android.hierarchyviewerlib.models.PixelPerfectModel.IImageChangeListener; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -161,9 +162,9 @@ public PixelPerfectTree(Composite parent) { } private void loadResources() { - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - mFileImage = loader.loadImage("file.png", Display.getDefault()); - mFolderImage = loader.loadImage("folder.png", Display.getDefault()); + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mFileImage = imageFactory.getImageByName("file.png"); + mFolderImage = imageFactory.getImageByName("folder.png"); } private DisposeListener mDisposeListener = new DisposeListener() { diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PropertyViewer.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PropertyViewer.java index bf0b6541..08efbe30 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PropertyViewer.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/PropertyViewer.java @@ -18,7 +18,6 @@ import com.android.annotations.NonNull; import com.android.annotations.VisibleForTesting; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.device.IHvDevice; import com.android.hierarchyviewerlib.models.TreeViewModel; @@ -29,6 +28,7 @@ import com.android.hierarchyviewerlib.ui.util.DrawableViewNode; import com.android.hierarchyviewerlib.ui.util.TreeColumnResizer; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ComboBoxCellEditor; @@ -343,8 +343,8 @@ public PropertyViewer(Composite parent) { addControlListener(mControlListener); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - mImage = imageLoader.loadImage("picker.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + mImage = imageFactory.getImageByName("picker.png"); //$NON-NLS-1$ treeChanged(); } diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeView.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeView.java index c3798cbc..4fa5691f 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeView.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeView.java @@ -16,7 +16,6 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.models.TreeViewModel; import com.android.hierarchyviewerlib.models.TreeViewModel.ITreeChangeListener; @@ -25,6 +24,7 @@ import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Point; import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Rectangle; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -178,14 +178,14 @@ public void keyTraversed(TraverseEvent e) { } private void loadResources() { - ImageLoader loader = ImageLoader.getLoader(this.getClass()); - sRedImage = loader.loadImage("red.png", Display.getDefault()); //$NON-NLS-1$ - sYellowImage = loader.loadImage("yellow.png", Display.getDefault()); //$NON-NLS-1$ - sGreenImage = loader.loadImage("green.png", Display.getDefault()); //$NON-NLS-1$ - sNotSelectedImage = loader.loadImage("not-selected.png", Display.getDefault()); //$NON-NLS-1$ - sSelectedImage = loader.loadImage("selected.png", Display.getDefault()); //$NON-NLS-1$ - sFilteredImage = loader.loadImage("filtered.png", Display.getDefault()); //$NON-NLS-1$ - sFilteredSelectedImage = loader.loadImage("selected-filtered.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + sRedImage = imageFactory.getImageByName("red.png"); //$NON-NLS-1$ + sYellowImage = imageFactory.getImageByName("yellow.png"); //$NON-NLS-1$ + sGreenImage = imageFactory.getImageByName("green.png"); //$NON-NLS-1$ + sNotSelectedImage = imageFactory.getImageByName("not-selected.png"); //$NON-NLS-1$ + sSelectedImage = imageFactory.getImageByName("selected.png"); //$NON-NLS-1$ + sFilteredImage = imageFactory.getImageByName("filtered.png"); //$NON-NLS-1$ + sFilteredSelectedImage = imageFactory.getImageByName("selected-filtered.png"); //$NON-NLS-1$ mBoxColor = new Color(Display.getDefault(), new RGB(225, 225, 225)); mTextBackgroundColor = new Color(Display.getDefault(), new RGB(82, 82, 82)); if (mScaledSelectedImage != null) { diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeViewOverview.java b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeViewOverview.java index 1bb5594f..87181a3c 100644 --- a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeViewOverview.java +++ b/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/com/android/hierarchyviewerlib/ui/TreeViewOverview.java @@ -16,13 +16,14 @@ package com.android.hierarchyviewerlib.ui; -import com.android.ddmuilib.ImageLoader; +import com.android.hierarchyviewerlib.HierarchyViewerDirector; import com.android.hierarchyviewerlib.models.TreeViewModel; import com.android.hierarchyviewerlib.models.TreeViewModel.ITreeChangeListener; import com.android.hierarchyviewerlib.ui.util.DrawableViewNode; import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Point; import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Rectangle; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -90,12 +91,12 @@ public TreeViewOverview(Composite parent) { } private void loadResources() { - ImageLoader loader = ImageLoader.getLoader(this.getClass()); - sNotSelectedImage = loader.loadImage("not-selected.png", Display.getDefault()); //$NON-NLS-1$ - sSelectedImage = loader.loadImage("selected-small.png", Display.getDefault()); //$NON-NLS-1$ - sFilteredImage = loader.loadImage("filtered.png", Display.getDefault()); //$NON-NLS-1$ + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + sNotSelectedImage = imageFactory.getImageByName("not-selected.png"); //$NON-NLS-1$ + sSelectedImage = imageFactory.getImageByName("selected-small.png"); //$NON-NLS-1$ + sFilteredImage = imageFactory.getImageByName("filtered.png"); //$NON-NLS-1$ sFilteredSelectedImage = - loader.loadImage("selected-filtered-small.png", Display.getDefault()); //$NON-NLS-1$ + imageFactory.getImageByName("selected-filtered-small.png"); //$NON-NLS-1$ } private DisposeListener mDisposeListener = new DisposeListener() { diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/META-INF/MANIFEST.MF b/andmore-swt/org.eclipse.andmore.sdkuilib/META-INF/MANIFEST.MF index fa75ea08..c75d3709 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/META-INF/MANIFEST.MF +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/META-INF/MANIFEST.MF @@ -1,28 +1,29 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Localization: plugin -Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.andmore.sdkuilib;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: %Bundle-Vendor -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", - org.eclipse.equinox.common;bundle-version="3.8.0", - org.eclipse.jface;bundle-version="3.12.2", - org.apache.httpcomponents.httpclient;bundle-version="4.1.3", - org.apache.httpcomponents.httpcore;bundle-version="4.1.4", - org.eclipse.andmore.swt, - org.eclipse.andmore.ddmuilib, - org.eclipse.andmore.swtmenubar, - com.google.gson;bundle-version="2.2.4" -Bundle-ClassPath: ., - libs/commons-compress-1.8.1.jar -Export-Package: com.android.sdkuilib.internal.repository, - com.android.sdkuilib.internal.repository.core, - com.android.sdkuilib.internal.repository.icons, - com.android.sdkuilib.internal.repository.ui, - com.android.sdkuilib.internal.tasks, - com.android.sdkuilib.internal.widgets, - com.android.sdkuilib.repository, - com.android.sdkuilib.ui -Import-Package: com.android.sdklib.repository +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Localization: plugin +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.andmore.sdkuilib;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: %Bundle-Vendor +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.commands;bundle-version="3.8.1", + org.eclipse.equinox.common;bundle-version="3.8.0", + org.eclipse.jface;bundle-version="3.12.2", + org.apache.httpcomponents.httpclient;bundle-version="4.1.3", + org.apache.httpcomponents.httpcore;bundle-version="4.1.4", + org.eclipse.andmore.swt, + org.eclipse.andmore.ddmuilib, + org.eclipse.andmore.swtmenubar, + com.google.gson;bundle-version="2.2.4", + org.eclipse.core.runtime;bundle-version="3.12.0", + org.eclipse.andmore.ddms;bundle-version="0.5.2" +Bundle-ClassPath: ., + libs/commons-compress-1.8.1.jar +Export-Package: com.android.sdkuilib.repository, + com.android.sdkuilib.ui, + com.android.sdkuilib.widgets, + org.eclipse.andmore.sdktool +Import-Package: com.android.sdklib.repository, + org.eclipse.ui.plugin +Bundle-ActivationPolicy: lazy +Bundle-Activator: org.eclipse.andmore.sdktool.SdkUserInterfacePlugin diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/build.properties b/andmore-swt/org.eclipse.andmore.sdkuilib/build.properties index 70d2e7a7..93e4b252 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/build.properties +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/build.properties @@ -3,5 +3,6 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ libs/,\ - plugin.properties + plugin.properties,\ + icons/ diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/accept_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/accept_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/accept_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/accept_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/addon_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/addon_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/addon_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/addon_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/android_icon_128.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/android_icon_128.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/android_icon_128.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/android_icon_128.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/android_icon_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/android_icon_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/android_icon_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/android_icon_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/archive_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/archive_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/archive_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/archive_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/broken_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/broken_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/broken_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/broken_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/broken_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/broken_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/broken_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/broken_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/buildtool_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/buildtool_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/buildtool_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/buildtool_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/device.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/device.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/device.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/device.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/doc_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/doc_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/doc_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/doc_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/emulator.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/emulator.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/emulator.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/emulator.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/error_icon_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/error_icon_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/error_icon_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/error_icon_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/extra_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/extra_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/extra_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/extra_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/incompat_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/incompat_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/incompat_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/incompat_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/log_off_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/log_off_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/log_off_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/log_off_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/log_on_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/log_on_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/log_on_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/log_on_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/nopkg_icon_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/nopkg_icon_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/nopkg_icon_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/nopkg_icon_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_incompat_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_incompat_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_incompat_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_incompat_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_installed_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_installed_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_installed_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_installed_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_new_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_new_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_new_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_new_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_update_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_update_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkg_update_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkg_update_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkgcat_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkgcat_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkgcat_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkgcat_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkgcat_other_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkgcat_other_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/pkgcat_other_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/pkgcat_other_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/platform_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/platform_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/platform_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/platform_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/platformtool_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/platformtool_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/platformtool_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/platformtool_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/reject_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/reject_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/reject_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/reject_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sample_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/sample_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sample_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/sample_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sdkman_logo_128.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/sdkman_logo_128.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sdkman_logo_128.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/sdkman_logo_128.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/source_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/source_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/source_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/source_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/status_ok_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/status_ok_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/status_ok_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/status_ok_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/stop_disabled_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/stop_disabled_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/stop_disabled_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/stop_disabled_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/stop_enabled_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/stop_enabled_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/stop_enabled_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/stop_enabled_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sysimg_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/sysimg_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/sysimg_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/sysimg_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-tv_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-tv_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-tv_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-tv_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-tv_32.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-tv_32.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-tv_32.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-tv_32.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-wear_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-wear_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-wear_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-wear_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-wear_32.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-wear_32.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_android-wear_32.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_android-wear_32.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_default_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_default_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_default_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_default_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_default_32.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_default_32.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tag_default_32.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tag_default_32.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tool_pkg_16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/tool_pkg_16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/tool_pkg_16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/tool_pkg_16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/unknown_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/unknown_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/unknown_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/unknown_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/warning_icon16.png b/andmore-swt/org.eclipse.andmore.sdkuilib/icons/warning_icon16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/warning_icon16.png rename to andmore-swt/org.eclipse.andmore.sdkuilib/icons/warning_icon16.png diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/libs/.gitignore b/andmore-swt/org.eclipse.andmore.sdkuilib/libs/.gitignore new file mode 100644 index 00000000..cfa4c651 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/libs/.gitignore @@ -0,0 +1 @@ +/commons-compress-1.8.1.jar diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/plugin.xml b/andmore-swt/org.eclipse.andmore.sdkuilib/plugin.xml new file mode 100644 index 00000000..b60f62ae --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/plugin.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/pom.xml b/andmore-swt/org.eclipse.andmore.sdkuilib/pom.xml index 803cf57a..02b253c6 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/pom.xml +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/pom.xml @@ -13,6 +13,11 @@ 0.5.2-SNAPSHOT + + org.apache.commons + commons-compress + 1.8.1 + junit junit @@ -77,6 +82,33 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + initialize + + copy + + + + + org.apache.commons + commons-compress + 1.8.1 + + + ${project.basedir}/libs + false + false + true + + + + + diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidTargetHash.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidTargetHash.java deleted file mode 100644 index e4520beb..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidTargetHash.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2013 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 com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.google.common.base.Splitter; - -import java.util.List; - - -/** - * Helper methods to manipulate hash strings used by {@link IAndroidTarget#hashString()}. - */ -public abstract class AndroidTargetHash { - - /** - * Prefix used to build hash strings for platform targets - * @see SdkManager#getTargetFromHashString(String) - */ - public static final String PLATFORM_HASH_PREFIX = "android-"; - - /** - * String to compute hash for add-on targets.
- * Format is {@code vendor:name:apiVersion}.
- * - * Important: the vendor and name compontents are the display strings, not the - * newer id strings. - */ - public static final String ADD_ON_FORMAT = "%s:%s:%s"; //$NON-NLS-1$ - - /** - * String used to get a hash to the platform target. - * This format is compatible with the PlatformPackage.installId(). - */ - static final String PLATFORM_HASH = PLATFORM_HASH_PREFIX + "%s"; - - /** - * Returns the hash string for a given platform version. - * - * @param version A non-null platform version. - * @return A non-null hash string uniquely representing this platform target. - */ - @NonNull - public static String getPlatformHashString(@NonNull AndroidVersion version) { - return String.format(AndroidTargetHash.PLATFORM_HASH, version.getApiString()); - } - - /** - * Returns the {@link AndroidVersion} for the given hash string, - * if it represents a platform. If the hash string represents a preview platform, - * the returned {@link AndroidVersion} will have an unknown API level (set to 1 - * or a known matching API level.) - * - * @param hashString the hash string (e.g. "android-19" or "android-CUPCAKE") - * or a pure API level for convenience (e.g. "19" instead of the proper "android-19") - * @return a platform, or null - */ - @Nullable - public static AndroidVersion getPlatformVersion(@NonNull String hashString) { - if (hashString.startsWith(PLATFORM_HASH_PREFIX)) { - String suffix = hashString.substring(PLATFORM_HASH_PREFIX.length()); - if (!suffix.isEmpty()) { - if (Character.isDigit(suffix.charAt(0))) { - try { - int api = Integer.parseInt(suffix); - return new AndroidVersion(api, null); - } catch (NumberFormatException ignore) {} - } else { - int api = SdkVersionInfo.getApiByBuildCode(suffix, false); - if (api < 1) { - api = 1; - } - return new AndroidVersion(api, suffix); - } - } - } else if (!hashString.isEmpty() && Character.isDigit(hashString.charAt(0))) { - // For convenience, interpret a single integer as the proper "android-NN" form. - try { - int api = Integer.parseInt(hashString); - return new AndroidVersion(api, null); - } catch (NumberFormatException ignore) {} - } - - return null; - } - - @Nullable - public static AndroidVersion getAddOnVersion(@NonNull String hashString) { - List parts = Splitter.on(':').splitToList(hashString); - if (parts.size() != 3) { - return null; - } - - String apiLevelPart = parts.get(2); - try { - int apiLevel = Integer.parseInt(apiLevelPart); - return new AndroidVersion(apiLevel, null); - } catch (NumberFormatException e) { - return null; - } - } - - /** - * Gets the API level from a hash string, either a platform version or add-on version. - * - * @see #getAddOnVersion(String) - * @see #getPlatformVersion(String) - */ - @Nullable - public static AndroidVersion getVersionFromHash(@NonNull String hashString) { - if (isPlatform(hashString)) { - return getPlatformVersion(hashString); - } else { - return getAddOnVersion(hashString); - } - } - - /** - * Returns the hash string for a given add-on. - * - * @param addonVendorDisplay A non-null vendor. When using an {@link IdDisplay} source, - * this parameter should be the {@link IdDisplay#getDisplay()}. - * @param addonNameDisplay A non-null add-on name. When using an {@link IdDisplay} source, - * this parameter should be the {@link IdDisplay#getDisplay()}. - * @param version A non-null platform version (the addon's base platform version) - * @return A non-null hash string uniquely representing this add-on target. - */ - public static String getAddonHashString( - @NonNull String addonVendorDisplay, - @NonNull String addonNameDisplay, - @NonNull AndroidVersion version) { - return String.format(ADD_ON_FORMAT, - addonVendorDisplay, - addonNameDisplay, - version.getApiString()); - } - - /** - * Returns the hash string for a given target (add-on or platform.) - * - * @param target A non-null target. - * @return A non-null hash string uniquely representing this target. - */ - public static String getTargetHashString(@NonNull IAndroidTarget target) { - if (target.isPlatform()) { - return getPlatformHashString(target.getVersion()); - } else { - return getAddonHashString( - target.getVendor(), - target.getName(), - target.getVersion()); - } - } - - /** - * Given a hash string, indicates whether this is a platform hash string. - * If not, it's an addon hash string. - * - * @param hashString The hash string to test. - * @return True if this hash string starts by the platform prefix. - */ - public static boolean isPlatform(@NonNull String hashString) { - return hashString.startsWith(PLATFORM_HASH_PREFIX); - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidVersion.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidVersion.java deleted file mode 100644 index 49dffbc1..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/AndroidVersion.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2009 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 com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.PkgProps; - -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * Represents the version of a target or device. - *

- * A version is defined by an API level and an optional code name. - *

  • Release versions of the Android platform are identified by their API level (integer), - * (technically the code name for release version is "REL" but this class will return - * null instead.)
  • - *
  • Preview versions of the platform are identified by a code name. Their API level - * is usually set to the value of the previous platform.
- *

- * While this class contains both values, its goal is to abstract them, so that code comparing 2+ - * versions doesn't have to deal with the logic of handle both values. - *

- * There are some cases where ones may want to access the values directly. This can be done - * with {@link #getApiLevel()} and {@link #getCodename()}. - *

- * For generic UI display of the API version, {@link #getApiString()} is to be used. - */ -public final class AndroidVersion implements Comparable { - - private final int mApiLevel; - private final String mCodename; - - /** The default AndroidVersion for minSdkVersion and targetSdkVersion if not specified */ - public static final AndroidVersion DEFAULT = new AndroidVersion(1, null); - - /** - * Thrown when an {@link AndroidVersion} object could not be created. - * @see AndroidVersion#AndroidVersion(Properties) - */ - public static final class AndroidVersionException extends Exception { - private static final long serialVersionUID = 1L; - - AndroidVersionException(String message, Throwable cause) { - super(message, cause); - } - } - - /** - * Creates an {@link AndroidVersion} with the given api level and codename. - * Codename should be null for a release version, otherwise it's a preview codename. - */ - public AndroidVersion(int apiLevel, @Nullable String codename) { - mApiLevel = apiLevel; - mCodename = sanitizeCodename(codename); - } - - /** - * Creates an {@link AndroidVersion} from {@link Properties}, with default values if the - * {@link Properties} object doesn't contain the expected values. - *

The {@link Properties} is expected to have been filled with - * {@link #saveProperties(Properties)}. - */ - public AndroidVersion(@Nullable Properties properties, - int defaultApiLevel, - @Nullable String defaultCodeName) { - if (properties == null) { - mApiLevel = defaultApiLevel; - mCodename = sanitizeCodename(defaultCodeName); - } else { - mApiLevel = Integer.parseInt(properties.getProperty(PkgProps.VERSION_API_LEVEL, - Integer.toString(defaultApiLevel))); - mCodename = sanitizeCodename( - properties.getProperty(PkgProps.VERSION_CODENAME, defaultCodeName)); - } - } - - /** - * Creates an {@link AndroidVersion} from {@link Properties}. The properties must contain - * android version information, or an exception will be thrown. - * @throws AndroidVersionException if no Android version information have been found - * - * @see #saveProperties(Properties) - */ - public AndroidVersion(@NonNull Properties properties) throws AndroidVersionException { - Exception error = null; - - String apiLevel = properties.getProperty(PkgProps.VERSION_API_LEVEL, null/*defaultValue*/); - if (apiLevel != null) { - try { - mApiLevel = Integer.parseInt(apiLevel); - mCodename = sanitizeCodename(properties.getProperty(PkgProps.VERSION_CODENAME, - null/*defaultValue*/)); - return; - } catch (NumberFormatException e) { - error = e; - } - } - - // reaching here means the Properties object did not contain the apiLevel which is required. - throw new AndroidVersionException(PkgProps.VERSION_API_LEVEL + " not found!", error); - } - - /** - * Creates an {@link AndroidVersion} from a string that may be an integer API - * level or a string codename. - *

- * Important: An important limitation of this method is that cannot possible - * recreate the API level integer from a pure string codename. This is only OK to use - * if the caller can guarantee that only {@link #getApiString()} will be used later. - * Wrong things will happen if the caller then tries to resolve the numeric - * {@link #getApiLevel()}. - * - * @param apiOrCodename A non-null API integer or a codename in its "ALL_CAPS" format. - * "REL" is notable not a valid codename. - * @throws AndroidVersionException if the input isn't a pure integer or doesn't look like - * a valid string codename. - */ - public AndroidVersion(@NonNull String apiOrCodename) throws AndroidVersionException { - int apiLevel = 0; - String codename = null; - try { - apiLevel = Integer.parseInt(apiOrCodename); - } catch (NumberFormatException ignore) { - // We don't know the API level. Android platform codenames are all caps. - // REL is a release-reserved keyword which we can use here. - - if (!SdkConstants.CODENAME_RELEASE.equals(apiOrCodename)) { - if (Pattern.matches("[A-Z_]+", apiOrCodename)) { - codename = apiOrCodename; - } - } - } - - mApiLevel = apiLevel; - mCodename = sanitizeCodename(codename); - - if (mApiLevel <= 0 && codename == null) { - throw new AndroidVersionException( - "Invalid android API or codename " + apiOrCodename, //$NON-NLS-1$ - null); - } - } - - public void saveProperties(@NonNull Properties props) { - props.setProperty(PkgProps.VERSION_API_LEVEL, Integer.toString(mApiLevel)); - if (mCodename != null) { - props.setProperty(PkgProps.VERSION_CODENAME, mCodename); - } - } - - /** - * Returns the api level as an integer. - *

For target that are in preview mode, this can be superseded by - * {@link #getCodename()}. - *

To display the API level in the UI, use {@link #getApiString()}, which will use the - * codename if applicable. - * @see #getCodename() - * @see #getApiString() - */ - public int getApiLevel() { - return mApiLevel; - } - - /** - * Returns the API level as an integer. If this is a preview platform, it - * will return the expected final version of the API rather than the current API - * level. This is the "feature level" as opposed to the "release level" returned by - * {@link #getApiLevel()} in the sense that it is useful when you want - * to check the presence of a given feature from an API, and we consider the feature - * present in preview platforms as well. - * - * @return the API level of this version, +1 for preview platforms - */ - public int getFeatureLevel() { - //noinspection VariableNotUsedInsideIf - return mCodename != null ? mApiLevel + 1 : mApiLevel; - } - - /** - * Returns the version code name if applicable, null otherwise. - *

If the codename is non null, then the API level should be ignored, and this should be - * used as a unique identifier of the target instead. - */ - @Nullable - public String getCodename() { - return mCodename; - } - - /** - * Returns a string representing the API level and/or the code name. - */ - @NonNull - public String getApiString() { - if (mCodename != null) { - return mCodename; - } - - return Integer.toString(mApiLevel); - } - - /** - * Returns whether or not the version is a preview version. - */ - public boolean isPreview() { - return mCodename != null; - } - - /** - * Checks whether a device running a version similar to the receiver can run a project compiled - * for the given version. - *

- * Be aware that this is not a perfect test, as other properties could break compatibility - * despite this method returning true. For a more comprehensive test, see - * {@link IAndroidTarget#canRunOn(IAndroidTarget)}. - *

- * Nevertheless, when testing if an application can run on a device (where there is no - * access to the list of optional libraries), this method can give a good indication of whether - * there is a chance the application could run, or if there's a direct incompatibility. - */ - public boolean canRun(@NonNull AndroidVersion appVersion) { - // if the application is compiled for a preview version, the device must be running exactly - // the same. - if (appVersion.mCodename != null) { - return appVersion.mCodename.equals(mCodename); - } - - // otherwise, we check the api level (note that a device running a preview version - // will have the api level of the previous platform). - return mApiLevel >= appVersion.mApiLevel; - } - - /** - * Returns true if the AndroidVersion is an API level equals to - * apiLevel. - */ - public boolean equals(int apiLevel) { - return mCodename == null && apiLevel == mApiLevel; - } - - /** - * Compares the receiver with either an {@link AndroidVersion} object or a {@link String} - * object. - *

If obj is a {@link String}, then the method will first check if it's a string - * representation of a number, in which case it'll compare it to the api level. Otherwise, it'll - * compare it against the code name. - *

For all other type of object give as parameter, this method will return - * false. - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof AndroidVersion) { - AndroidVersion version = (AndroidVersion)obj; - - if (mCodename == null) { - return version.mCodename == null && - mApiLevel == version.mApiLevel; - } else { - return mCodename.equals(version.mCodename) && - mApiLevel == version.mApiLevel; - } - - } else if (obj instanceof String) { - // if we have a code name, this must match. - if (mCodename != null) { - return mCodename.equals(obj); - } - - // else we try to convert to a int and compare to the api level - try { - int value = Integer.parseInt((String)obj); - return value == mApiLevel; - } catch (NumberFormatException e) { - // not a number? we'll return false below. - } - } - - return false; - } - - @Override - public int hashCode() { - if (mCodename != null) { - return mCodename.hashCode(); - } - - // there may be some collisions between the hashcode of the codename and the api level - // but it's acceptable. - return mApiLevel; - } - - /** - * Returns a string with the API Level and optional codename. - * Useful for debugging. - * For display purpose, please use {@link #getApiString()} instead. - */ - @Override - public String toString() { - String s = String.format("API %1$d", mApiLevel); //$NON-NLS-1$ - if (isPreview()) { - s += String.format(", %1$s preview", mCodename); //$NON-NLS-1$ - } - return s; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the Object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - */ - @Override - public int compareTo(@NonNull AndroidVersion o) { - return compareTo(o.mApiLevel, o.mCodename); - } - - public int compareTo(int apiLevel, @Nullable String codename) { - if (mCodename == null) { - if (codename == null) { - return mApiLevel - apiLevel; - } else { - if (mApiLevel == apiLevel) { - return -1; // same api level but argument is a preview for next version - } - - return mApiLevel - apiLevel; - } - } else { - // 'this' is a preview - if (mApiLevel == apiLevel) { - if (codename == null) { - return +1; - } else { - return mCodename.compareTo(codename); // strange case where the 2 previews - // have different codename? - } - } else { - return mApiLevel - apiLevel; - } - } - } - - /** - * Compares this version with the specified API and returns true if this version - * is greater or equal than the requested API -- that is the current version is a - * suitable min-api-level for the argument API. - */ - public boolean isGreaterOrEqualThan(int api) { - return compareTo(api, null /*codename*/) >= 0; - } - - /** - * Sanitizes the codename string according to the following rules: - * - A codename should be {@code null} for a release version or it should be a non-empty - * string for an actual preview. - * - In input, spacing is trimmed since it is irrelevant. - * - An empty string or the special codename "REL" means a release version - * and is converted to {@code null}. - * - * @param codename A possible-null codename. - * @return Null for a release version or a non-empty codename. - */ - @Nullable - private static String sanitizeCodename(@Nullable String codename) { - if (codename != null) { - codename = codename.trim(); - if (codename.isEmpty() || SdkConstants.CODENAME_RELEASE.equals(codename)) { - codename = null; - } - } - return codename; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/BuildToolInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/BuildToolInfo.java deleted file mode 100644 index 39fefd6d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/BuildToolInfo.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2013 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 static com.android.SdkConstants.FD_LIB; -import static com.android.SdkConstants.FN_AAPT; -import static com.android.SdkConstants.FN_AIDL; -import static com.android.SdkConstants.FN_BCC_COMPAT; -import static com.android.SdkConstants.FN_DEXDUMP; -import static com.android.SdkConstants.FN_DX; -import static com.android.SdkConstants.FN_DX_JAR; -import static com.android.SdkConstants.FN_JACK; -import static com.android.SdkConstants.FN_JILL; -import static com.android.SdkConstants.FN_LD_ARM; -import static com.android.SdkConstants.FN_LD_MIPS; -import static com.android.SdkConstants.FN_LD_X86; -import static com.android.SdkConstants.FN_RENDERSCRIPT; -import static com.android.SdkConstants.FN_SPLIT_SELECT; -import static com.android.SdkConstants.FN_ZIPALIGN; -import static com.android.SdkConstants.OS_FRAMEWORK_RS; -import static com.android.SdkConstants.OS_FRAMEWORK_RS_CLANG; -import static com.android.sdklib.BuildToolInfo.PathId.AAPT; -import static com.android.sdklib.BuildToolInfo.PathId.AIDL; -import static com.android.sdklib.BuildToolInfo.PathId.ANDROID_RS; -import static com.android.sdklib.BuildToolInfo.PathId.ANDROID_RS_CLANG; -import static com.android.sdklib.BuildToolInfo.PathId.BCC_COMPAT; -import static com.android.sdklib.BuildToolInfo.PathId.DEXDUMP; -import static com.android.sdklib.BuildToolInfo.PathId.DX; -import static com.android.sdklib.BuildToolInfo.PathId.DX_JAR; -import static com.android.sdklib.BuildToolInfo.PathId.JACK; -import static com.android.sdklib.BuildToolInfo.PathId.JILL; -import static com.android.sdklib.BuildToolInfo.PathId.LD_ARM; -import static com.android.sdklib.BuildToolInfo.PathId.LD_MIPS; -import static com.android.sdklib.BuildToolInfo.PathId.LD_X86; -import static com.android.sdklib.BuildToolInfo.PathId.LLVM_RS_CC; -import static com.android.sdklib.BuildToolInfo.PathId.SPLIT_SELECT; -import static com.android.sdklib.BuildToolInfo.PathId.ZIP_ALIGN; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.utils.ILogger; -import com.google.common.collect.Maps; - -import java.io.File; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Information on a specific build-tool folder. - *

- * For unit tests, see: - * - sdklib/src/test/.../LocalSdkTest - * - sdklib/src/test/.../SdkManagerTest - * - sdklib/src/test/.../BuildToolInfoTest - */ -public class BuildToolInfo { - - /** Name of the file read by {@link #getRuntimeProps()} */ - private static final String FN_RUNTIME_PROPS = "runtime.properties"; - - /** - * Property in {@link #FN_RUNTIME_PROPS} indicating the desired runtime JVM. - * Type: {@link NoPreviewRevision#toShortString()}, e.g. "1.7.0" - */ - private static final String PROP_RUNTIME_JVM = "Runtime.Jvm"; - - /** - * First version with native multi-dex support. - */ - public static final int SDK_LEVEL_FOR_MULTIDEX_NATIVE_SUPPORT = 21; - - public enum PathId { - /** OS Path to the target's version of the aapt tool. */ - AAPT("1.0.0"), - /** OS Path to the target's version of the aidl tool. */ - AIDL("1.0.0"), - /** OS Path to the target's version of the dx tool. */ - DX("1.0.0"), - /** OS Path to the target's version of the dx.jar file. */ - DX_JAR("1.0.0"), - /** OS Path to the llvm-rs-cc binary for Renderscript. */ - LLVM_RS_CC("1.0.0"), - /** OS Path to the Renderscript include folder. */ - ANDROID_RS("1.0.0"), - /** OS Path to the Renderscript(clang) include folder. */ - ANDROID_RS_CLANG("1.0.0"), - - DEXDUMP("1.0.0"), - - // --- NEW IN 18.1.0 --- - - /** OS Path to the bcc_compat tool. */ - BCC_COMPAT("18.1.0"), - /** OS Path to the ARM linker. */ - LD_ARM("18.1.0"), - /** OS Path to the X86 linker. */ - LD_X86("18.1.0"), - /** OS Path to the MIPS linker. */ - LD_MIPS("18.1.0"), - - // --- NEW IN 19.1.0 --- - ZIP_ALIGN("19.1.0"), - - // --- NEW IN 21.x.y --- - JACK("21.1.0"), - JILL("21.1.0"), - - SPLIT_SELECT("22.0.0"); - - /** - * min revision this element was introduced. - * Controls {@link BuildToolInfo#isValid(ILogger)} - */ - private final FullRevision mMinRevision; - - /** - * Creates the enum with a min revision in which this - * tools appeared in the build tools. - * - * @param minRevision the min revision. - */ - PathId(@NonNull String minRevision) { - mMinRevision = FullRevision.parseRevision(minRevision); - } - - /** - * Returns whether the enum of present in a given rev of the build tools. - * - * @param fullRevision the build tools revision. - * @return true if the tool is present. - */ - boolean isPresentIn(@NonNull FullRevision fullRevision) { - return fullRevision.compareTo(mMinRevision) >= 0; - } - } - - /** The build-tool revision. */ - @NonNull - private final FullRevision mRevision; - - /** The path to the build-tool folder specific to this revision. */ - @NonNull - private final File mPath; - - private final Map mPaths = Maps.newEnumMap(PathId.class); - - public BuildToolInfo(@NonNull FullRevision revision, @NonNull File path) { - mRevision = revision; - mPath = path; - - add(AAPT, FN_AAPT); - add(AIDL, FN_AIDL); - add(DX, FN_DX); - add(DX_JAR, FD_LIB + File.separator + FN_DX_JAR); - add(LLVM_RS_CC, FN_RENDERSCRIPT); - add(ANDROID_RS, OS_FRAMEWORK_RS); - add(ANDROID_RS_CLANG, OS_FRAMEWORK_RS_CLANG); - add(DEXDUMP, FN_DEXDUMP); - add(BCC_COMPAT, FN_BCC_COMPAT); - add(LD_ARM, FN_LD_ARM); - add(LD_X86, FN_LD_X86); - add(LD_MIPS, FN_LD_MIPS); - add(ZIP_ALIGN, FN_ZIPALIGN); - add(JACK, FN_JACK); - add(JILL, FN_JILL); - add(SPLIT_SELECT, FN_SPLIT_SELECT); - } - - public BuildToolInfo( - @NonNull FullRevision revision, - @NonNull File mainPath, - @NonNull File aapt, - @NonNull File aidl, - @NonNull File dx, - @NonNull File dxJar, - @NonNull File llmvRsCc, - @NonNull File androidRs, - @NonNull File androidRsClang, - @Nullable File bccCompat, - @Nullable File ldArm, - @Nullable File ldX86, - @Nullable File ldMips, - @NonNull File zipAlign) { - mRevision = revision; - mPath = mainPath; - add(AAPT, aapt); - add(AIDL, aidl); - add(DX, dx); - add(DX_JAR, dxJar); - add(LLVM_RS_CC, llmvRsCc); - add(ANDROID_RS, androidRs); - add(ANDROID_RS_CLANG, androidRsClang); - add(ZIP_ALIGN, zipAlign); - - if (bccCompat != null) { - add(BCC_COMPAT, bccCompat); - } else if (BCC_COMPAT.isPresentIn(revision)) { - throw new IllegalArgumentException("BCC_COMPAT required in " + revision.toString()); - } - if (ldArm != null) { - add(LD_ARM, ldArm); - } else if (LD_ARM.isPresentIn(revision)) { - throw new IllegalArgumentException("LD_ARM required in " + revision.toString()); - } - - if (ldX86 != null) { - add(LD_X86, ldX86); - } else if (LD_X86.isPresentIn(revision)) { - throw new IllegalArgumentException("LD_X86 required in " + revision.toString()); - } - - if (ldMips != null) { - add(LD_MIPS, ldMips); - } else if (LD_MIPS.isPresentIn(revision)) { - throw new IllegalArgumentException("LD_MIPS required in " + revision.toString()); - } - } - - private void add(PathId id, String leaf) { - add(id, new File(mPath, leaf)); - } - - private void add(PathId id, File path) { - String str = path.getAbsolutePath(); - if (path.isDirectory() && str.charAt(str.length() - 1) != File.separatorChar) { - str += File.separatorChar; - } - mPaths.put(id, str); - } - - /** - * Returns the revision. - */ - @NonNull - public FullRevision getRevision() { - return mRevision; - } - - /** - * Returns the build-tool revision-specific folder. - *

- * For compatibility reasons, use {@link #getPath(PathId)} if you need the path to a - * specific tool. - */ - @NonNull - public File getLocation() { - return mPath; - } - - /** - * Returns the path of a build-tool component. - * - * @param pathId the id representing the path to return. - * @return The absolute path for that tool, with a / separator if it's a folder. - * Null if the path-id is unknown. - */ - public String getPath(PathId pathId) { - assert pathId.isPresentIn(mRevision); - - return mPaths.get(pathId); - } - - /** - * Checks whether the build-tool is valid by verifying that the expected binaries - * are actually present. This checks that all known paths point to a valid file - * or directory. - * - * @param log An optional logger. If non-null, errors will be printed there. - * @return True if the build-tool folder contains all the expected tools. - */ - public boolean isValid(@Nullable ILogger log) { - for (Map.Entry entry : mPaths.entrySet()) { - File f = new File(entry.getValue()); - // check if file is missing. It's only ok if the revision of the build-tools - // is lower than the min rev of the element. - if (!f.exists() && entry.getKey().isPresentIn(mRevision)) { - if (log != null) { - log.warning("Build-tool %1$s is missing %2$s at %3$s", //$NON-NLS-1$ - mRevision.toString(), - entry.getKey(), f.getAbsolutePath()); - } - return false; - } - } - return true; - } - - /** - * Parses the build-tools runtime.props file, if present. - * - * @return The properties from runtime.props if present, otherwise an empty properties set. - */ - @NonNull - public Properties getRuntimeProps() { - LegacyFileOp fop = new LegacyFileOp(); - return fop.loadProperties(new File(mPath, FN_RUNTIME_PROPS)); - } - - /** - * Checks whether this build-tools package can run on the current JVM. - * - * @return True if the build-tools package has a Runtime.Jvm property and it is lesser or - * equal to the current JVM version. - * False if the property is present and the requirement is not met. - * True if there's an error parsing either versions and the comparison cannot be made. - */ - public boolean canRunOnJvm() { - Properties props = getRuntimeProps(); - String required = props.getProperty(PROP_RUNTIME_JVM); - if (required == null) { - // No requirement ==> accepts. - return true; - } - try { - NoPreviewRevision requiredVersion = NoPreviewRevision.parseRevision(required); - NoPreviewRevision currentVersion = getCurrentJvmVersion(); - return currentVersion.compareTo(requiredVersion) >= 0; - - } catch (NumberFormatException ignore) { - // Either we failed to parse the property version or the running JVM version. - // Right now take the relaxed policy of accepting it if we can't compare. - return true; - } - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - @Nullable - protected NoPreviewRevision getCurrentJvmVersion() throws NumberFormatException { - String javav = System.getProperty("java.version"); //$NON-NLS-1$ - // java Version is typically in the form "1.2.3_45" and we just need to keep up to "1.2.3" - // since our revision numbers are in 3-parts form (1.2.3). - Pattern p = Pattern.compile("((\\d+)(\\.\\d+)?(\\.\\d+)?).*"); //$NON-NLS-1$ - Matcher m = p.matcher(javav); - if (m.matches()) { - return NoPreviewRevision.parseRevision(m.group(1)); - } - return null; - } - - /** - * Returns a debug representation suitable for unit-tests. - * Note that unit-tests need to clean up the paths to avoid inconsistent results. - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(""); //$NON-NLS-1$ - return builder.toString(); - } - - private String getPathString() { - StringBuilder sb = new StringBuilder("{"); - - for (Map.Entry entry : mPaths.entrySet()) { - if (entry.getKey().isPresentIn(mRevision)) { - if (sb.length() > 1) { - sb.append(", "); - } - sb.append(entry.getKey()).append('=').append(entry.getValue()); - } - } - - sb.append('}'); - - return sb.toString(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/IAndroidTarget.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/IAndroidTarget.java deleted file mode 100644 index 6606bc84..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/IAndroidTarget.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * 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 com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.descriptors.IdDisplay; - -import java.io.File; -import java.util.List; -import java.util.Map; - - - -/** - * A version of Android that applications can target when building. - */ -public interface IAndroidTarget extends Comparable { - - /** OS Path to the "android.jar" file. */ - int ANDROID_JAR = 1; - /** OS Path to the "framework.aidl" file. */ - int ANDROID_AIDL = 2; - /** OS Path to the "samples" folder which contains sample projects. */ - int SAMPLES = 4; - /** OS Path to the "skins" folder which contains the emulator skins. */ - int SKINS = 5; - /** OS Path to the "templates" folder which contains the templates for new projects. */ - int TEMPLATES = 6; - /** OS Path to the "data" folder which contains data & libraries for the SDK tools. */ - int DATA = 7; - /** OS Path to the "attrs.xml" file. */ - int ATTRIBUTES = 8; - /** OS Path to the "attrs_manifest.xml" file. */ - int MANIFEST_ATTRIBUTES = 9; - /** OS Path to the "data/layoutlib.jar" library. */ - int LAYOUT_LIB = 10; - /** OS Path to the "data/res" folder. */ - int RESOURCES = 11; - /** OS Path to the "data/fonts" folder. */ - int FONTS = 12; - /** OS Path to the "data/widgets.txt" file. */ - int WIDGETS = 13; - /** OS Path to the "data/activity_actions.txt" file. */ - int ACTIONS_ACTIVITY = 14; - /** OS Path to the "data/broadcast_actions.txt" file. */ - int ACTIONS_BROADCAST = 15; - /** OS Path to the "data/service_actions.txt" file. */ - int ACTIONS_SERVICE = 16; - /** OS Path to the "data/categories.txt" file. */ - int CATEGORIES = 17; - /** OS Path to the "sources" folder. */ - int SOURCES = 18; - /** OS Path to the target specific docs */ - int DOCS = 19; - /** OS Path to the "ant" folder which contains the ant build rules (ver 2 and above) */ - int ANT = 24; - /** OS Path to the "uiautomator.jar" file. */ - int UI_AUTOMATOR_JAR = 27; - - - /** - * Return value for {@link #getUsbVendorId()} meaning no USB vendor IDs are defined by the - * Android target. - */ - int NO_USB_ID = 0; - - /** An optional library provided by an Android Target */ - interface OptionalLibrary { - /** The name of the library, as used in the manifest (<uses-library>). */ - @NonNull - String getName(); - /** Location of the jar file. */ - @NonNull - File getJar(); - /** Description of the library. */ - @NonNull - String getDescription(); - /** Whether the library requires a manifest entry */ - boolean isManifestEntryRequired(); - } - - /** - * Returns the target location. - */ - String getLocation(); - - /** - * Returns the name of the vendor of the target. - */ - String getVendor(); - - /** - * Returns the name of the target. - */ - String getName(); - - /** - * Returns the full name of the target, possibly including vendor name. - */ - String getFullName(); - - /** - * Returns the name to be displayed when representing all the libraries this target contains. - */ - String getClasspathName(); - - /** - * Returns the name to be displayed when representing all the libraries this target contains. - */ - String getShortClasspathName(); - - /** - * Returns the description of the target. - */ - String getDescription(); - - /** - * Returns the version of the target. This is guaranteed to be non-null. - */ - @NonNull - AndroidVersion getVersion(); - - /** - * Returns the platform version as a readable string. - */ - String getVersionName(); - - /** Returns the revision number for the target. */ - int getRevision(); - - /** - * Returns true if the target is a standard Android platform. - */ - boolean isPlatform(); - - /** - * Returns the parent target. This is likely to only be non null if - * {@link #isPlatform()} returns false - */ - IAndroidTarget getParent(); - - /** - * Returns the path of a platform component. - * @param pathId the id representing the path to return. - * Any of the constants defined in the {@link IAndroidTarget} interface can be used. - */ - String getPath(int pathId); - - /** - * Returns the path of a platform component. - *

- * This is like the legacy {@link #getPath(int)} method except it returns a {@link File}. - * - * @param pathId the id representing the path to return. - * Any of the constants defined in the {@link IAndroidTarget} interface can be used. - */ - File getFile(int pathId); - - /** - * Returns a BuildToolInfo for backward compatibility. If an older SDK is used this will return - * paths located in the platform-tools, otherwise it'll return paths located in the latest - * build-tools. - * @return a BuildToolInfo or null if none are available. - */ - BuildToolInfo getBuildToolInfo(); - - /** - * Returns the boot classpath for this target. - * In most case, this is similar to calling {@link #getPath(int)} with - * {@link IAndroidTarget#ANDROID_JAR}. - * - * @return a non null list of the boot classpath. - */ - @NonNull - List getBootClasspath(); - - /** - * Returns a list of optional libraries for this target. - * - * These libraries are not automatically added to the classpath. - * Using them requires adding a uses-library entry in the manifest. - * - * @return a list of libraries. - * - * @see OptionalLibrary#getName() - */ - @NonNull - List getOptionalLibraries(); - - /** - * Returns the additional libraries for this target. - * - * These libraries are automatically added to the classpath, but using them requires - * adding a uses-library entry in the manifest. - * - * @return a list of libraries. - * - * @see OptionalLibrary#getName() - */ - @NonNull - List getAdditionalLibraries(); - - /** - * Returns whether the target is able to render layouts. - */ - boolean hasRenderingLibrary(); - - /** - * Returns the available skin folders for this target. - *

- * To get the skin names, use {@link File#getName()}.
- * Skins come either from: - *

    - *
  • a platform ({@code sdk/platforms/N/skins/name})
  • - *
  • an add-on ({@code sdk/addons/name/skins/name})
  • - *
  • a tagged system-image ({@code sdk/system-images/platform-N/tag/abi/skins/name}.)
  • - *
- * The array can be empty but not null. - */ - @NonNull - File[] getSkins(); - - /** - * Returns the default skin folder for this target. - *

- * To get the skin name, use {@link File#getName()}. - */ - @Nullable - File getDefaultSkin(); - - /** - * Returns the list of libraries available for a given platform. - * - * @return an array of libraries provided by the platform or null if there is none. - */ - String[] getPlatformLibraries(); - - /** - * Return the value of a given property for this target. - * @return the property value or null if it was not found. - */ - String getProperty(String name); - - /** - * Returns the value of a given property for this target as an Integer value. - *

If the value is missing or is not an integer, the method will return the given default - * value. - * @param name the name of the property to return - * @param defaultValue the default value to return. - * - * @see Integer#decode(String) - */ - Integer getProperty(String name, Integer defaultValue); - - /** - * Returns the value of a given property for this target as a Boolean value. - *

If the value is missing or is not an boolean, the method will return the given default - * value. - * - * @param name the name of the property to return - * @param defaultValue the default value to return. - * - * @see Boolean#valueOf(String) - */ - - Boolean getProperty(String name, Boolean defaultValue); - - /** - * Returns all the properties associated with this target. This can be null if the target has - * no properties. - */ - Map getProperties(); - - /** - * Returns the USB Vendor ID for the vendor of this target. - *

If the target defines no USB Vendor ID, then the method return 0. - */ - int getUsbVendorId(); - - /** - * Returns an array of system images for this target. - * The array can be empty but not null. - */ - ISystemImage[] getSystemImages(); - - /** - * Returns the system image information for the given {@code tag} and {@code abiType}. - * - * @param tag A tag id-display. - * @param abiType An ABI type string. - * @return An existing {@link ISystemImage} for the requested {@code abiType} - * or null if none exists for this type. - */ - @Nullable - ISystemImage getSystemImage(@NonNull IdDisplay tag, @NonNull String abiType); - - /** - * Returns whether the given target is compatible with the receiver. - *

- * This means that a project using the receiver's target can run on the given target. - *
- * Example: - *

-     * CupcakeTarget.canRunOn(DonutTarget) == true
-     * 
. - * - * @param target the IAndroidTarget to test. - */ - boolean canRunOn(IAndroidTarget target); - - /** - * 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. - *

- * See {@link AndroidTargetHash} for helper methods to manipulate hash strings. - */ - String hashString(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/ISystemImage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/ISystemImage.java deleted file mode 100644 index b39a9081..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/ISystemImage.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.repository.descriptors.IdDisplay; - -import java.io.File; - - -/** - * Describes a system image as used by an {@link IAndroidTarget}. - * A system image has an installation path, a location type and an ABI type. - */ -public interface ISystemImage extends Comparable { - - /** Indicates the type of location for the system image folder in the SDK. */ - enum LocationType { - /** - * The system image is located in the legacy platform's {@link SdkConstants#FD_IMAGES} - * folder. - *

- * Used by both platform and add-ons. - */ - IN_LEGACY_FOLDER, - - /** - * The system image is located in a sub-directory of the platform's - * {@link SdkConstants#FD_IMAGES} folder, allowing for multiple system - * images within the platform. - *

- * Used by both platform and add-ons. - */ - IN_IMAGES_SUBFOLDER, - - /** - * The system image is located in the new SDK's {@link SdkConstants#FD_SYSTEM_IMAGES} - * folder. Supported as of Tools R14 and Repository XSD version 5. - *

- * Used only by both platform up to Tools R22.6. - * Supported for add-ons as of Tools R22.8. - */ - IN_SYSTEM_IMAGE, - } - - /** Returns the actual location of an installed system image. */ - @NonNull - File getLocation(); - - /** Indicates the location strategy for this system image in the SDK. */ - @NonNull - LocationType getLocationType(); - - /** Returns the tag of the system image. */ - @NonNull - IdDisplay getTag(); - - /** Returns the vendor for an add-on's system image, or null for a platform system-image. */ - @Nullable - IdDisplay getAddonVendor(); - - /** - * Returns the ABI type. - * See {@link Abi} for a full list. - * Cannot be null nor empty. - */ - @NonNull - String getAbiType(); - - /** - * Returns the skins embedded in the system image.
- * Only supported by system images using {@link LocationType#IN_SYSTEM_IMAGE}.
- * The skins listed here are merged in the {@link IAndroidTarget#getSkins()} list. - * @return A non-null skin list, possibly empty. - */ - @NonNull - File[] getSkins(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/LegacyAndroidVersion.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/LegacyAndroidVersion.java deleted file mode 100644 index e6d31e09..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/LegacyAndroidVersion.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.android.sdklib; - -import java.util.Properties; - -public class LegacyAndroidVersion { - - private AndroidVersion androidVersion; - - public LegacyAndroidVersion(Properties properties) - throws AndroidVersion.AndroidVersionException - { - Exception error = null; - - String apiLevel = properties.getProperty("AndroidVersion.ApiLevel", null); - if (apiLevel != null) { - try - { - String codename = sanitizeCodename(properties.getProperty("AndroidVersion.CodeName", null)); - androidVersion = new AndroidVersion(Integer.parseInt(apiLevel), codename); - return; - } - catch (NumberFormatException e) - { - error = e; - } - } - throw new AndroidVersion.AndroidVersionException("AndroidVersion.ApiLevel not found!", error); - } - - public AndroidVersion getAndroidVersion() - { - return androidVersion; - } - - private static String sanitizeCodename(String codename) - { - if (codename != null) - { - codename = codename.trim(); - if ((codename.isEmpty()) || ("REL".equals(codename))) { - codename = null; - } - } - return codename; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkManager.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkManager.java deleted file mode 100644 index 91b57037..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkManager.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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 com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.internal.androidTarget.AddOnTarget; -import com.android.sdklib.internal.androidTarget.PlatformTarget; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgType; -import com.android.sdklib.repository.local.LocalExtraPkgInfo; -import com.android.sdklib.repository.local.LocalPkgInfo; -import com.android.sdklib.repository.local.LocalSdk; -import com.android.utils.ILogger; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * The SDK manager parses the SDK folder and gives access to the content. - * @see PlatformTarget - * @see AddOnTarget - */ -public class SdkManager { - - @SuppressWarnings("unused") - private static final boolean DEBUG = System.getenv("SDKMAN_DEBUG") != null; //$NON-NLS-1$ - - /** Preference file containing the usb ids for adb */ - private static final String ADB_INI_FILE = "adb_usb.ini"; //$NON-NLS-1$ - //0--------90--------90--------90--------90--------90--------90--------90--------9 - private static final String ADB_INI_HEADER = - "# ANDROID 3RD PARTY USB VENDOR ID LIST -- DO NOT EDIT.\n" + //$NON-NLS-1$ - "# USE 'android update adb' TO GENERATE.\n" + //$NON-NLS-1$ - "# 1 USB VENDOR ID PER LINE.\n"; //$NON-NLS-1$ - - /** Embedded reference to the new local SDK object. */ - private final LocalSdk mLocalSdk; - - /** - * Create a new {@link SdkManager} instance. - * External users should use {@link #createManager(String, ILogger)}. - * - * @param osSdkPath the location of the SDK. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SdkManager(@NonNull String osSdkPath) { - mLocalSdk = new LocalSdk(new File(osSdkPath)); - } - - /** - * Creates an @{linkplain SdkManager} for an existing @{link LocalSdk}. - * - * @param localSdk the SDK to use with the SDK manager - */ - private SdkManager(@NonNull LocalSdk localSdk) { - mLocalSdk = localSdk; - } - - /** - * Creates an {@link SdkManager} for a given sdk location. - * @param osSdkPath the location of the SDK. - * @param log the ILogger object receiving warning/error from the parsing. - * @return the created {@link SdkManager} or null if the location is not valid. - */ - @Nullable - public static SdkManager createManager( - @NonNull String osSdkPath, - @NonNull ILogger log) { - try { - SdkManager manager = new SdkManager(osSdkPath); - manager.reloadSdk(log); - - return manager; - } catch (Throwable throwable) { - log.error(throwable, "Error parsing the sdk."); - } - - return null; - } - - /** - * Creates an @{linkplain SdkManager} for an existing @{link LocalSdk}. - * - * @param localSdk the SDK to use with the SDK manager - */ - @NonNull - public static SdkManager createManager(@NonNull LocalSdk localSdk) { - return new SdkManager(localSdk); - } - - @NonNull - public LocalSdk getLocalSdk() { - return mLocalSdk; - } - - /** - * Reloads the content of the SDK. - * - * @param log the ILogger object receiving warning/error from the parsing. - */ - public void reloadSdk(@NonNull ILogger log) { - mLocalSdk.clearLocalPkg(PkgType.PKG_ALL); - } - - /** - * Checks whether any of the SDK platforms/add-ons/build-tools have changed on-disk - * since we last loaded the SDK. This does not reload the SDK nor does it - * change the underlying targets. - * - * @return True if at least one directory or source.prop has changed. - */ - public boolean hasChanged() { - return hasChanged(null); - } - - /** - * Checks whether any of the SDK platforms/add-ons/build-tools have changed on-disk - * since we last loaded the SDK. This does not reload the SDK nor does it - * change the underlying targets. - * - * @param log An optional logger used to print verbose info on what changed. Can be null. - * @return True if at least one directory or source.prop has changed. - */ - public boolean hasChanged(@Nullable ILogger log) { - return mLocalSdk.hasChanged(EnumSet.of(PkgType.PKG_PLATFORM, - PkgType.PKG_ADDON, - PkgType.PKG_BUILD_TOOLS)); - } - - /** - * Returns the location of the SDK. - */ - @NonNull - public String getLocation() { - File f = mLocalSdk.getLocation(); - // Our LocalSdk is created with a file path, so we know the location won't be null. - assert f != null; - return f.getPath(); - } - - /** - * Returns the targets (platforms & addons) that are available in the SDK. - * The target list is created on demand the first time then cached. - * It will not refreshed unless {@link #reloadSdk(ILogger)} is called. - *

- * The array can be empty but not null. - */ - @NonNull - public IAndroidTarget[] getTargets() { - return mLocalSdk.getTargets(); - } - - /** - * Returns an unmodifiable set of known build-tools revisions. Can be empty but not null. - * Deprecated. I don't think anything uses this. - */ - @Deprecated - @NonNull - public Set getBuildTools() { - LocalPkgInfo[] pkgs = mLocalSdk.getPkgsInfos(PkgType.PKG_BUILD_TOOLS); - TreeSet bt = new TreeSet(); - for (LocalPkgInfo pkg : pkgs) { - IPkgDesc d = pkg.getDesc(); - if (d.hasFullRevision()) { - bt.add(d.getFullRevision()); - } - } - return Collections.unmodifiableSet(bt); - } - - /** - * Returns the highest build-tool revision known. Can be null. - * - * @return The highest build-tool revision known, or null. - */ - @Nullable - public BuildToolInfo getLatestBuildTool() { - return mLocalSdk.getLatestBuildTool(); - } - - /** - * Returns the {@link BuildToolInfo} for the given revision. - * - * @param revision The requested revision. - * @return A {@link BuildToolInfo}. Can be null if {@code revision} is null or is - * not part of the known set returned by {@link #getBuildTools()}. - */ - @Nullable - public BuildToolInfo getBuildTool(@Nullable FullRevision revision) { - return mLocalSdk.getBuildTool(revision); - } - - /** - * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}. - * - * @param hash the {@link IAndroidTarget} hash string. - * @return The matching {@link IAndroidTarget} or null. - */ - @Nullable - public IAndroidTarget getTargetFromHashString(@Nullable String hash) { - return mLocalSdk.getTargetFromHashString(hash); - } - - /** - * Updates adb with the USB devices declared in the SDK add-ons. - * @throws AndroidLocationException - * @throws IOException - */ - public void updateAdb() throws AndroidLocationException, IOException { - FileWriter writer = null; - try { - // get the android prefs location to know where to write the file. - File adbIni = new File(AndroidLocation.getFolder(), ADB_INI_FILE); - writer = new FileWriter(adbIni); - - // first, put all the vendor id in an HashSet to remove duplicate. - HashSet set = new HashSet(); - IAndroidTarget[] targets = getTargets(); - for (IAndroidTarget target : targets) { - if (target.getUsbVendorId() != IAndroidTarget.NO_USB_ID) { - set.add(target.getUsbVendorId()); - } - } - - // write file header. - writer.write(ADB_INI_HEADER); - - // now write the Id in a text file, one per line. - for (Integer i : set) { - writer.write(String.format("0x%04x\n", i)); //$NON-NLS-1$ - } - } finally { - if (writer != null) { - writer.close(); - } - } - } - - /** - * Returns the greatest {@link LayoutlibVersion} found amongst all platform - * targets currently loaded in the SDK. - *

- * We only started recording Layoutlib Versions recently in the platform meta data - * so it's possible to have an SDK with many platforms loaded but no layoutlib - * version defined. - * - * @return The greatest {@link LayoutlibVersion} or null if none is found. - * @deprecated This does NOT solve the right problem and will be changed later. - */ - @Deprecated - @Nullable - public LayoutlibVersion getMaxLayoutlibVersion() { - LayoutlibVersion maxVersion = null; - - for (IAndroidTarget target : getTargets()) { - if (target instanceof PlatformTarget) { - LayoutlibVersion lv = ((PlatformTarget) target).getLayoutlibVersion(); - if (lv != null) { - if (maxVersion == null || lv.compareTo(maxVersion) > 0) { - maxVersion = lv; - } - } - } - } - - return maxVersion; - } - - /** - * Returns a map of the root samples directories located in the SDK/extras packages. - * No guarantee is made that the extras' samples directory actually contain any valid samples. - * The only guarantee is that the root samples directory actually exists. - * The map is { File: Samples root directory => String: Extra package display name. } - * - * @return A non-null possibly empty map of extra samples directories and their associated - * extra package display name. - */ - @NonNull - public Map getExtraSamples() { - - LocalPkgInfo[] pkgsInfos = mLocalSdk.getPkgsInfos(PkgType.PKG_EXTRA); - Map samples = new HashMap(); - - for (LocalPkgInfo info : pkgsInfos) { - assert info instanceof LocalExtraPkgInfo; - - File root = info.getLocalDir(); - File path = new File(root, SdkConstants.FD_SAMPLES); - if (path.isDirectory()) { - samples.put(path, info.getListDescription()); - continue; - } - // Some old-style extras simply have a single "sample" directory. - // Accept it if it contains an AndroidManifest.xml. - path = new File(root, SdkConstants.FD_SAMPLE); - if (path.isDirectory() && - new File(path, SdkConstants.FN_ANDROID_MANIFEST_XML).isFile()) { - samples.put(path, info.getListDescription()); - } - } - - return samples; - } - - /** - * Returns a map of all the extras found in the local SDK with their major revision. - *

- * Map keys are in the form "vendor-id/path-id". These ids uniquely identify an extra package. - * The version is the incremental integer major revision of the package. - * - * @return A non-null possibly empty map of { string "vendor/path" => integer major revision } - * @deprecated Starting with add-on schema 6, extras can have full revisions instead of just - * major revisions. This API only returns the major revision. Callers should be modified - * to use the new {code LocalSdk.getPkgInfo(PkgType.PKG_EXTRAS)} API instead. - */ - @Deprecated - @NonNull - public Map getExtrasVersions() { - LocalPkgInfo[] pkgsInfos = mLocalSdk.getPkgsInfos(PkgType.PKG_EXTRA); - Map extraVersions = new TreeMap(); - - for (LocalPkgInfo info : pkgsInfos) { - assert info instanceof LocalExtraPkgInfo; - if (info instanceof LocalExtraPkgInfo) { - LocalExtraPkgInfo ei = (LocalExtraPkgInfo) info; - IPkgDesc d = ei.getDesc(); - String vendor = d.getVendor().getId(); - String path = d.getPath(); - int majorRev = d.getFullRevision().getMajor(); - - extraVersions.put(vendor + '/' + path, majorRev); - } - } - - return extraVersions; - } - - /** Returns the platform tools version if installed, null otherwise. */ - @Nullable - public String getPlatformToolsVersion() { - LocalPkgInfo info = mLocalSdk.getPkgInfo(PkgType.PKG_PLATFORM_TOOLS); - IPkgDesc d = info == null ? null : info.getDesc(); - if (d != null && d.hasFullRevision()) { - return d.getFullRevision().toShortString(); - } - - return null; - } - - - // ------------- - - public static class LayoutlibVersion implements Comparable { - private final int mApi; - private final int mRevision; - - public static final int NOT_SPECIFIED = 0; - - public LayoutlibVersion(int api, int revision) { - mApi = api; - mRevision = revision; - } - - public int getApi() { - return mApi; - } - - public int getRevision() { - return mRevision; - } - - @Override - public int compareTo(@NonNull LayoutlibVersion rhs) { - boolean useRev = this.mRevision > NOT_SPECIFIED && rhs.mRevision > NOT_SPECIFIED; - int lhsValue = (this.mApi << 16) + (useRev ? this.mRevision : 0); - int rhsValue = (rhs.mApi << 16) + (useRev ? rhs.mRevision : 0); - return lhsValue - rhsValue; - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkVersionInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkVersionInfo.java deleted file mode 100644 index cfedbf1a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SdkVersionInfo.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2013 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 com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.base.Strings; - -import java.util.Locale; - -/** Information about available SDK Versions */ -public class SdkVersionInfo { - /** - * The highest known API level. Note that the tools may also look at the - * installed platforms to see if they can find more recently released - * platforms, e.g. when the tools have not yet been updated for a new - * release. This number is used as a baseline and any more recent platforms - * found can be used to increase the highest known number. - */ - public static final int HIGHEST_KNOWN_API = 23; - - /** - * Like {@link #HIGHEST_KNOWN_API} but does not include preview platforms - */ - public static final int HIGHEST_KNOWN_STABLE_API = 22; - - /** - * The lowest active API level in the ecosystem. This number will change over time - * as the distribution of older platforms decreases. - */ - public static final int LOWEST_ACTIVE_API = 8; - - /** - * Returns the Android version and code name of the given API level, or null - * if not known. The highest number (inclusive) that is supported - * is {@link SdkVersionInfo#HIGHEST_KNOWN_API}. - * - * @param api the api level - * @return a suitable version display name - */ - @Nullable - public static String getAndroidName(int api) { - // See http://source.android.com/source/build-numbers.html - String codeName = getCodeName(api); - String name = getVersionString(api); - if (name == null) { - return String.format("API %1$d", api); - } else if (codeName == null) { - return String.format("API %1$d: Android %2$s", api, name); - } else { - return String.format("API %1$d: Android %2$s (%3$s)", api, name, codeName); - } - } - - @Nullable - public static String getVersionString(int api) { - switch (api) { - case 1: return "1.0"; - case 2: return "1.1"; - case 3: return "1.5"; - case 4: return "1.6"; - case 5: return "2.0"; - case 6: return "2.0.1"; - case 7: return "2.1"; - case 8: return "2.2"; - case 9: return "2.3"; - case 10: return "2.3.3"; - case 11: return "3.0"; - case 12: return "3.1"; - case 13: return "3.2"; - case 14: return "4.0"; - case 15: return "4.0.3"; - case 16: return "4.1"; - case 17: return "4.2"; - case 18: return "4.3"; - case 19: return "4.4"; - case 20: return "4.4"; - case 21: return "5.0"; - case 22: return "5.1"; - case 23: return "5.X"; - // If you add more versions here, also update #getBuildCodes and - // #HIGHEST_KNOWN_API - - default: return null; - } - } - - @Nullable - public static String getCodeName(int api) { - switch (api) { - case 1: - case 2: - return null; - case 3: - return "Cupcake"; - case 4: - return "Donut"; - case 5: - case 6: - case 7: - return "Eclair"; - case 8: - return "Froyo"; - case 9: - case 10: - return "Gingerbread"; - case 11: - case 12: - case 13: - return "Honeycomb"; - case 14: - case 15: - return "IceCreamSandwich"; - case 16: - case 17: - case 18: - return "Jelly Bean"; - case 19: - return "KitKat"; - case 20: - return "KitKat Wear"; - case 21: - case 22: - return "Lollipop"; - case 23: - return "MNC"; - - // If you add more versions here, also update #getBuildCodes and - // #HIGHEST_KNOWN_API - - default: return null; - } - } - - /** - * Returns the applicable build code (for - * {@code android.os.Build.VERSION_CODES}) for the corresponding API level, - * or null if it's unknown. The highest number (inclusive) that is supported - * is {@link SdkVersionInfo#HIGHEST_KNOWN_API}. - * - * @param api the API level to look up a version code for - * @return the corresponding build code field name, or null - */ - @Nullable - public static String getBuildCode(int api) { - // See http://developer.android.com/reference/android/os/Build.VERSION_CODES.html - switch (api) { - case 1: return "BASE"; //$NON-NLS-1$ - case 2: return "BASE_1_1"; //$NON-NLS-1$ - case 3: return "CUPCAKE"; //$NON-NLS-1$ - case 4: return "DONUT"; //$NON-NLS-1$ - case 5: return "ECLAIR"; //$NON-NLS-1$ - case 6: return "ECLAIR_0_1"; //$NON-NLS-1$ - case 7: return "ECLAIR_MR1"; //$NON-NLS-1$ - case 8: return "FROYO"; //$NON-NLS-1$ - case 9: return "GINGERBREAD"; //$NON-NLS-1$ - case 10: return "GINGERBREAD_MR1"; //$NON-NLS-1$ - case 11: return "HONEYCOMB"; //$NON-NLS-1$ - case 12: return "HONEYCOMB_MR1"; //$NON-NLS-1$ - case 13: return "HONEYCOMB_MR2"; //$NON-NLS-1$ - case 14: return "ICE_CREAM_SANDWICH"; //$NON-NLS-1$ - case 15: return "ICE_CREAM_SANDWICH_MR1"; //$NON-NLS-1$ - case 16: return "JELLY_BEAN"; //$NON-NLS-1$ - case 17: return "JELLY_BEAN_MR1"; //$NON-NLS-1$ - case 18: return "JELLY_BEAN_MR2"; //$NON-NLS-1$ - case 19: return "KITKAT"; //$NON-NLS-1$ - case 20: return "KITKAT_WATCH"; //$NON-NLS-1$ - case 21: return "LOLLIPOP"; //$NON-NLS-1$ - case 22: return "LOLLIPOP_MR1"; //$NON-NLS-1$ - case 23: return "MNC"; //$NON-NLS-1$ - // If you add more versions here, also update #getAndroidName and - // #HIGHEST_KNOWN_API - } - - return null; - } - - /** - * Returns the API level of the given build code (e.g. JELLY_BEAN_MR1 => 17), or -1 if not - * recognized - * - * @param buildCode the build code name (not case sensitive) - * @param recognizeUnknowns if true, treat an unrecognized code name as a newly released - * platform the tools are not yet aware of, and set its API level to - * some higher number than all the currently known API versions - * @return the API level, or -1 if not recognized (unless recognizeUnknowns is true, in which - * {@link #HIGHEST_KNOWN_API} plus one is returned - */ - public static int getApiByBuildCode(@NonNull String buildCode, boolean recognizeUnknowns) { - for (int api = 1; api <= HIGHEST_KNOWN_API; api++) { - String code = getBuildCode(api); - if (code != null && code.equalsIgnoreCase(buildCode)) { - return api; - } - } - - if (buildCode.equalsIgnoreCase("L")) { - return 21; // For now the Build class also provides this as an alias to Lollipop - } - - return recognizeUnknowns ? HIGHEST_KNOWN_API + 1 : -1; - } - - /** - * Returns the API level of the given preview code name (e.g. JellyBeanMR2 => 17), or -1 if not - * recognized - * - * @param previewName the preview name (not case sensitive) - * @param recognizeUnknowns if true, treat an unrecognized code name as a newly released - * platform the tools are not yet aware of, and set its API level to - * some higher number than all the currently known API versions - * @return the API level, or -1 if not recognized (unless recognizeUnknowns is true, in which - * {@link #HIGHEST_KNOWN_API} plus one is returned - */ - public static int getApiByPreviewName(@NonNull String previewName, boolean recognizeUnknowns) { - // JellyBean => JELLY_BEAN - String codeName = camelCaseToUnderlines(previewName).toUpperCase(Locale.US); - return getApiByBuildCode(codeName, recognizeUnknowns); - } - - /** - * Converts a CamelCase word into an underlined_word - * - * @param string the CamelCase version of the word - * @return the underlined version of the word - */ - @NonNull - public static String camelCaseToUnderlines(@NonNull String string) { - if (string.isEmpty()) { - return string; - } - - StringBuilder sb = new StringBuilder(2 * string.length()); - int n = string.length(); - boolean lastWasUpperCase = Character.isUpperCase(string.charAt(0)); - for (int i = 0; i < n; i++) { - char c = string.charAt(i); - boolean isUpperCase = Character.isUpperCase(c); - if (isUpperCase && !lastWasUpperCase) { - sb.append('_'); - } - lastWasUpperCase = isUpperCase; - c = Character.toLowerCase(c); - sb.append(c); - } - - return sb.toString(); - } - - /** - * Converts an underlined_word into a CamelCase word - * - * @param string the underlined word to convert - * @return the CamelCase version of the word - */ - @NonNull - public static String underlinesToCamelCase(@NonNull String string) { - StringBuilder sb = new StringBuilder(string.length()); - int n = string.length(); - - int i = 0; - @SuppressWarnings("SpellCheckingInspection") - boolean upcaseNext = true; - for (; i < n; i++) { - char c = string.charAt(i); - if (c == '_') { - upcaseNext = true; - } else { - if (upcaseNext) { - c = Character.toUpperCase(c); - } - upcaseNext = false; - sb.append(c); - } - } - - return sb.toString(); - } - - /** - * Returns the {@link AndroidVersion} for a given version string, which is typically an API - * level number, but can also be a codename for a preview platform. Note: This should - * not be used to look up version names for build codes; for that, use {@link - * #getApiByBuildCode(String, boolean)}. The primary difference between this method is that - * {@link #getApiByBuildCode(String, boolean)} will return the final API number for a platform - * (e.g. for "KITKAT" it will return 19) whereas this method will return the API number for the - * codename as a preview platform (e.g. 18). - * - * @param apiOrPreviewName the version string - * @param targets an optional array of installed targets, if available. If the version - * string corresponds to a code name, this is used to search for a - * corresponding API level. - * @return an {@link com.android.sdklib.AndroidVersion}, or null if the version could not be - * determined (e.g. an empty or invalid API number or an unknown code name) - */ - @Nullable - public static AndroidVersion getVersion( - @Nullable String apiOrPreviewName, - @Nullable IAndroidTarget[] targets) { - if (Strings.isNullOrEmpty(apiOrPreviewName)) { - return null; - } - - if (Character.isDigit(apiOrPreviewName.charAt(0))) { - try { - int api = Integer.parseInt(apiOrPreviewName); - if (api >= 1) { - return new AndroidVersion(api, null); - } - return null; - } catch (NumberFormatException e) { - // Invalid version string - return null; - } - } - - // Codename - if (targets != null) { - for (int i = targets.length - 1; i >= 0; i--) { - IAndroidTarget target = targets[i]; - if (target.isPlatform()) { - AndroidVersion version = target.getVersion(); - if (version.isPreview() && apiOrPreviewName.equalsIgnoreCase(version.getCodename())) { - return new AndroidVersion(version.getApiLevel(), version.getCodename()); - } - } - } - } - - int api = getApiByPreviewName(apiOrPreviewName, false); - if (api != -1) { - return new AndroidVersion(api - 1, apiOrPreviewName); - } - - // Must be a future SDK platform - return new AndroidVersion(HIGHEST_KNOWN_API, apiOrPreviewName); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SystemImage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SystemImage.java deleted file mode 100644 index 79c9c41f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/SystemImage.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.internal.androidTarget.PlatformTarget; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.google.common.base.Objects; - -import java.io.File; -import java.util.Arrays; -import java.util.Locale; - - -/** - * Describes a system image as used by an {@link IAndroidTarget}. - * A system image has an installation path, a location type, a tag and an ABI type. - */ -public class SystemImage implements ISystemImage { - - public static final IdDisplay DEFAULT_TAG = new IdDisplay("default", //$NON-NLS-1$ - "Default"); //$NON-NLS-1$ - - @Deprecated - private final LocationType mLocationtype; - private final IdDisplay mTag; - private final IdDisplay mAddonVendor; - private final String mAbiType; - private final File mLocation; - private final File[] mSkins; - - /** - * Creates a {@link SystemImage} description for an existing platform system image folder. - * - * @param location The location of an installed system image. - * @param locationType Where the system image folder is located for this ABI. - * @param tag The tag of the system-image. Use {@link #DEFAULT_TAG} for backward compatibility. - * @param abiType The ABI type. For example, one of {@link SdkConstants#ABI_ARMEABI}, - * {@link SdkConstants#ABI_ARMEABI_V7A}, {@link SdkConstants#ABI_INTEL_ATOM} or - * {@link SdkConstants#ABI_MIPS}. - * @param skins A non-null, possibly empty list of skins specific to this system image. - */ - public SystemImage( - @NonNull File location, - @NonNull LocationType locationType, - @NonNull IdDisplay tag, - @NonNull String abiType, - @NonNull File[] skins) { - this(location, locationType, tag, null /*addonVendor*/, abiType, skins); - } - - /** - * Creates a {@link SystemImage} description for an existing system image folder, - * for either platform or add-on. - * - * @param location The location of an installed system image. - * @param locationType Where the system image folder is located for this ABI. - * @param tagName The tag of the system-image. - * For an add-on, the tag-id must match the add-on's name-id. - * @param addonVendor Non-null add-on vendor name. Null for platforms. - * @param abiType The ABI type. For example, one of {@link SdkConstants#ABI_ARMEABI}, - * {@link SdkConstants#ABI_ARMEABI_V7A}, {@link SdkConstants#ABI_INTEL_ATOM} or - * {@link SdkConstants#ABI_MIPS}. - * @param skins A non-null, possibly empty list of skins specific to this system image. - */ - public SystemImage( - @NonNull File location, - @NonNull LocationType locationType, - @NonNull IdDisplay tagName, - @Nullable IdDisplay addonVendor, - @NonNull String abiType, - @NonNull File[] skins) { - mLocation = location; - mLocationtype = locationType; - mTag = tagName; - mAddonVendor = addonVendor; - mAbiType = abiType; - mSkins = skins; - } - - /** - * Creates a {@link SystemImage} description for a non-existing platform system image folder. - * The actual location is computed based on the {@code locationType}. - * - * @param sdkManager The current SDK manager. - * @param locationType Where the system image folder is located for this ABI. - * @param tag The tag of the system-image. Use {@link #DEFAULT_TAG} for backward compatibility. - * @param abiType The ABI type. For example, one of {@link SdkConstants#ABI_ARMEABI}, - * {@link SdkConstants#ABI_ARMEABI_V7A}, {@link SdkConstants#ABI_INTEL_ATOM} or - * {@link SdkConstants#ABI_MIPS}. - * @param skins A non-null, possibly empty list of skins specific to this system image. - * @throws IllegalArgumentException if the {@code target} used for - * {@link ISystemImage.LocationType#IN_SYSTEM_IMAGE} is not a {@link PlatformTarget}. - */ - public SystemImage( - @NonNull SdkManager sdkManager, - @NonNull IAndroidTarget target, - @NonNull LocationType locationType, - @NonNull IdDisplay tag, - @NonNull String abiType, - @NonNull File[] skins) { - this(sdkManager, target, locationType, tag, null /*addonVendor*/, abiType, skins); - } - - - /** - * Creates a {@link SystemImage} description for a non-existing system image folder, - * for either platform or add-on. - * The actual location is computed based on the {@code locationType}. - * - * @param sdkManager The current SDK manager. - * @param locationType Where the system image folder is located for this ABI. - * @param tag The tag of the system-image. Use {@link #DEFAULT_TAG} for backward compatibility. - * @param addonVendor Non-null add-on vendor name. Null for platforms. - * @param abiType The ABI type. For example, one of {@link SdkConstants#ABI_ARMEABI}, - * {@link SdkConstants#ABI_ARMEABI_V7A}, {@link SdkConstants#ABI_INTEL_ATOM} or - * {@link SdkConstants#ABI_MIPS}. - * @param skins A non-null, possibly empty list of skins specific to this system image. - * @throws IllegalArgumentException if the {@code target} used for - * {@link ISystemImage.LocationType#IN_SYSTEM_IMAGE} is not a {@link PlatformTarget}. - */ - public SystemImage( - @NonNull SdkManager sdkManager, - @NonNull IAndroidTarget target, - @NonNull LocationType locationType, - @NonNull IdDisplay tag, - @Nullable IdDisplay addonVendor, - @NonNull String abiType, - @NonNull File[] skins) { - mLocationtype = locationType; - mTag = tag; - mAddonVendor = addonVendor; - mAbiType = abiType; - mSkins = skins; - - File location = null; - switch(locationType) { - case IN_LEGACY_FOLDER: - location = new File(target.getLocation(), SdkConstants.OS_IMAGES_FOLDER); - break; - - case IN_IMAGES_SUBFOLDER: - location = LegacyFileOp.append(target.getLocation(), SdkConstants.OS_IMAGES_FOLDER, abiType); - break; - - case IN_SYSTEM_IMAGE: - location = getCanonicalFolder(sdkManager.getLocation(), - target.getVersion(), - tag.getId(), - addonVendor == null ? null : addonVendor.getId(), - abiType); - break; - default: - // This is not supposed to happen unless LocationType is - // extended without adjusting this code. - assert false : "SystemImage used with an incorrect locationType"; //$NON-NLS-1$ - } - mLocation = location; - } - - /** - * Static helper method that returns the canonical path for a system-image that uses - * the {@link ISystemImage.LocationType#IN_SYSTEM_IMAGE} location type. - *

- * Such an image is located in {@code SDK/system-images/android-N/tag/abiType}. - * For this reason this method requires the root SDK as well as the platform, tag abd ABI type. - * - * @param sdkOsPath The OS path to the SDK. - * @param platformVersion The platform version. - * @param tagId An optional tag. If null, not tag folder is used. - * For legacy, use {@code SystemImage.DEFAULT_TAG.getId()}. - * @param addonVendorId An optional vendor-id for an add-on. If null, it's a platform sys-img. - * @param abiType An optional ABI type. If null, the parent directory is returned. - * @return A file that represents the location of the canonical system-image folder - * for this configuration. - */ - @NonNull - private static File getCanonicalFolder( - @NonNull String sdkOsPath, - @NonNull AndroidVersion platformVersion, - @Nullable String tagId, - @Nullable String addonVendorId, - @Nullable String abiType) { - File root; - if (addonVendorId == null) { - root = LegacyFileOp.append( - sdkOsPath, - SdkConstants.FD_SYSTEM_IMAGES, - AndroidTargetHash.getPlatformHashString(platformVersion)); - if (tagId != null) { - root = LegacyFileOp.append(root, tagId); - } - } else { - root = LegacyFileOp.append( - sdkOsPath, - SdkConstants.FD_SYSTEM_IMAGES, - AndroidTargetHash.getAddonHashString(addonVendorId, tagId, platformVersion)); - } - if (abiType == null) { - return root; - } else { - return LegacyFileOp.append(root, abiType); - } - } - - /** Returns the actual location of an installed system image. */ - @NonNull - @Override - public File getLocation() { - return mLocation; - } - - /** - * Indicates the location strategy for this system image in the SDK. - * @deprecated - */ - @NonNull - @Override - public LocationType getLocationType() { - return mLocationtype; - } - - /** Returns the tag of the system image. */ - @NonNull - @Override - public IdDisplay getTag() { - return mTag; - } - - /** Returns the vendor for an add-on's system image, or null for a platform system-image. */ - @Nullable - @Override - public IdDisplay getAddonVendor() { - return mAddonVendor; - } - - /** - * Returns the ABI type. - * See {@link Abi} for a full list. - * Cannot be null nor empty. - */ - @NonNull - @Override - public String getAbiType() { - return mAbiType; - } - - @NonNull - @Override - public File[] getSkins() { - return mSkins; - } - - /** - * Sort by tag & ABI name only. This is what matters from a user point of view. - */ - @Override - public int compareTo(ISystemImage other) { - int t = this.getTag().compareTo(other.getTag()); - if (t != 0) { - return t; - } - return this.getAbiType().compareToIgnoreCase(other.getAbiType()); - } - - /** - * Generates a string representation suitable for debug purposes. - * The string is not intended to be displayed to the user. - * - * {@inheritDoc} - */ - @NonNull - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("SystemImage"); - if (mAddonVendor != null) { - sb.append(" addon-vendor=").append(mAddonVendor.getId()).append(','); - } - sb.append(" tag=").append(mTag.getId()); - sb.append(", ABI=").append(mAbiType); - sb.append(", location ") - .append(mLocationtype.toString().replace('_', ' ').toLowerCase(Locale.US)) - .append("='") - .append(mLocation) - .append("'"); - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SystemImage)) { - return false; - } - SystemImage other = (SystemImage)o; - return mTag.equals(other.mTag) && mAbiType.equals(other.getAbiType()) && Objects.equal(mAddonVendor, other.mAddonVendor) - && mLocation.equals(other.mLocation) && Arrays.equals(mSkins, other.mSkins); - } - - @Override - public int hashCode() { - int hashCode = Objects.hashCode(mTag, mAbiType, mAddonVendor, mLocation); - hashCode *= 37; - hashCode += Arrays.hashCode(mSkins); - return hashCode; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/AddOnTarget.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/AddOnTarget.java deleted file mode 100644 index 83a3e554..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/AddOnTarget.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * 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.internal.androidTarget; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.google.common.collect.ImmutableList; - -import java.io.File; -import java.io.FileFilter; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -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}. - */ -public final class AddOnTarget implements IAndroidTarget { - - private final String mLocation; - private final PlatformTarget mBasePlatform; - private final String mName; - private final ISystemImage[] mSystemImages; - private final String mVendor; - private final int mRevision; - private final String mDescription; - private final boolean mHasRenderingLibrary; - private final boolean mHasRenderingResources; - - private File[] mSkins; - private File mDefaultSkin; - private ImmutableList mLibraries; - private int mVendorId = NO_USB_ID; - - /** - * 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 revision the revision of the add-on - * @param description the add-on description - * @param systemImages list of supported system images. Can be null or empty. - * @param libMap A map containing the optional libraries. The map key is the fully-qualified - * library name. The value is a 2 string array with the .jar filename, and the description. - * @param hasRenderingLibrary whether the addon has a custom layoutlib.jar - * @param hasRenderingResources whether the add has custom framework resources. - * @param basePlatform the platform the add-on is extending. - */ - public AddOnTarget( - String location, - String name, - String vendor, - int revision, - String description, - ISystemImage[] systemImages, - Map libMap, - boolean hasRenderingLibrary, - boolean hasRenderingResources, - PlatformTarget basePlatform) { - if (!location.endsWith(File.separator)) { - location = location + File.separator; - } - - mLocation = location; - mName = name; - mVendor = vendor; - mRevision = revision; - mDescription = description; - mHasRenderingLibrary = hasRenderingLibrary; - mHasRenderingResources = hasRenderingResources; - mBasePlatform = basePlatform; - - // If the add-on does not have any system-image of its own, the list here - // is empty and it's up to the callers to query the parent platform. - mSystemImages = systemImages == null ? new ISystemImage[0] : systemImages; - Arrays.sort(mSystemImages); - - // handle the optional libraries. - if (libMap != null) { - ImmutableList.Builder builder = ImmutableList.builder(); - for (Entry entry : libMap.entrySet()) { - String jarFile = entry.getValue()[0]; - String desc = entry.getValue()[1]; - builder.add(new OptionalLibraryImpl( - entry.getKey(), - new File(mLocation, SdkConstants.OS_ADDON_LIBS_FOLDER + jarFile), - desc, - true /*requireManifestEntry*/)); - } - mLibraries = builder.build(); - } else { - mLibraries = ImmutableList.of(); - } - } - - @Override - public String getLocation() { - return mLocation; - } - - @Override - public String getName() { - return mName; - } - - @Override - @Nullable - public ISystemImage getSystemImage(@NonNull IdDisplay tag, @NonNull String abiType) { - for (ISystemImage sysImg : mSystemImages) { - if (sysImg.getTag().equals(tag) && sysImg.getAbiType().equals(abiType)) { - return sysImg; - } - } - return null; - } - - @Override - public ISystemImage[] getSystemImages() { - return mSystemImages; - } - - @Override - public String getVendor() { - return mVendor; - } - - @Override - public String getFullName() { - return String.format("%1$s (%2$s)", mName, mVendor); - } - - @Override - public String getClasspathName() { - return String.format("%1$s [%2$s]", mName, mBasePlatform.getClasspathName()); - } - - @Override - public String getShortClasspathName() { - return String.format("%1$s [%2$s]", mName, mBasePlatform.getVersionName()); - } - - @Override - public String getDescription() { - return mDescription; - } - - @NonNull - @Override - public AndroidVersion getVersion() { - // this is always defined by the base platform - return mBasePlatform.getVersion(); - } - - @Override - public String getVersionName() { - return mBasePlatform.getVersionName(); - } - - @Override - public int getRevision() { - return mRevision; - } - - @Override - public boolean isPlatform() { - return false; - } - - @Override - public IAndroidTarget getParent() { - return mBasePlatform; - } - - @Override - public String getPath(int pathId) { - switch (pathId) { - case SKINS: - return mLocation + SdkConstants.OS_SKINS_FOLDER; - case DOCS: - return mLocation + SdkConstants.FD_DOCS + File.separator - + SdkConstants.FD_DOCS_REFERENCE; - - case LAYOUT_LIB: - if (mHasRenderingLibrary) { - return mLocation + SdkConstants.FD_DATA + File.separator - + SdkConstants.FN_LAYOUTLIB_JAR; - } - return mBasePlatform.getPath(pathId); - - case RESOURCES: - if (mHasRenderingResources) { - return mLocation + SdkConstants.FD_DATA + File.separator - + SdkConstants.FD_RES; - } - return mBasePlatform.getPath(pathId); - - case FONTS: - if (mHasRenderingResources) { - return mLocation + SdkConstants.FD_DATA + File.separator - + SdkConstants.FD_FONTS; - } - return mBasePlatform.getPath(pathId); - - case SAMPLES: - // only return the add-on samples folder if there is actually a sample (or more) - File sampleLoc = new File(mLocation, SdkConstants.FD_SAMPLES); - if (sampleLoc.isDirectory()) { - File[] files = sampleLoc.listFiles(new FileFilter() { - @Override - public boolean accept(File pathname) { - return pathname.isDirectory(); - } - - }); - if (files != null && files.length > 0) { - return sampleLoc.getAbsolutePath(); - } - } - //$FALL-THROUGH$ - default : - return mBasePlatform.getPath(pathId); - } - } - - @Override - public File getFile(int pathId) { - return new File(getPath(pathId)); - } - - @Override - public BuildToolInfo getBuildToolInfo() { - return mBasePlatform.getBuildToolInfo(); - } - - @Override @NonNull - public List getBootClasspath() { - return mBasePlatform.getBootClasspath(); - } - - @NonNull - @Override - public List getOptionalLibraries() { - return mBasePlatform.getOptionalLibraries(); - } - - @NonNull - @Override - public List getAdditionalLibraries() { - return mLibraries; - } - - @Override - public boolean hasRenderingLibrary() { - return mHasRenderingLibrary || mHasRenderingResources; - } - - @NonNull - @Override - public File[] getSkins() { - return mSkins; - } - - @Nullable - @Override - public File getDefaultSkin() { - return mDefaultSkin; - } - - /** - * Returns the list of libraries of the underlying platform. - * - * {@inheritDoc} - */ - @Override - public String[] getPlatformLibraries() { - return mBasePlatform.getPlatformLibraries(); - } - - @Override - public String getProperty(String name) { - return mBasePlatform.getProperty(name); - } - - @Override - public Integer getProperty(String name, Integer defaultValue) { - return mBasePlatform.getProperty(name, defaultValue); - } - - @Override - public Boolean getProperty(String name, Boolean defaultValue) { - return mBasePlatform.getProperty(name, defaultValue); - } - - @Override - public Map getProperties() { - return mBasePlatform.getProperties(); - } - - @Override - public int getUsbVendorId() { - return mVendorId; - } - - @Override - public boolean canRunOn(IAndroidTarget target) { - // basic test - if (target == this) { - return true; - } - - /* - * The method javadoc indicates: - * Returns whether the given target is compatible with the receiver. - *

A target is considered compatible if applications developed for the receiver can - * run on the given target. - */ - - // The receiver is an add-on. There are 2 big use cases: The add-on has libraries - // or the add-on doesn't (in which case we consider it a platform). - if (mLibraries.isEmpty()) { - return mBasePlatform.canRunOn(target); - } else { - // the only targets that can run the receiver are the same add-on in the same or later - // versions. - // first check: vendor/name - if (!mVendor.equals(target.getVendor()) || !mName.equals(target.getName())) { - return false; - } - - // now check the version. At this point since we checked the add-on part, - // we can revert to the basic check on version/codename which are done by the - // base platform already. - return mBasePlatform.canRunOn(target); - } - - } - - @Override - public String hashString() { - return String.format(AndroidTargetHash.ADD_ON_FORMAT, mVendor, mName, - mBasePlatform.getVersion().getApiString()); - } - - @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.getVersion().equals(addon.mBasePlatform.getVersion()); - } - - return false; - } - - /* - * Order by API level (preview/n count as between n and n+1). - * At the same API level, order as: Platform first, then add-on ordered by vendor and then name - * (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - @Override - public int compareTo(@NonNull IAndroidTarget target) { - // quick check. - if (this == target) { - return 0; - } - - int versionDiff = getVersion().compareTo(target.getVersion()); - - // only if the version are the same do we care about platform/add-ons. - if (versionDiff == 0) { - // platforms go before add-ons. - if (target.isPlatform()) { - return +1; - } else { - AddOnTarget targetAddOn = (AddOnTarget)target; - - // both are add-ons of the same version. Compare per vendor then by name - int vendorDiff = mVendor.compareTo(targetAddOn.mVendor); - if (vendorDiff == 0) { - return mName.compareTo(targetAddOn.mName); - } else { - return vendorDiff; - } - } - - } - - return versionDiff; - } - - /** - * Returns a string representation suitable for debugging. - * The representation is not intended for display to the user. - * - * The representation is also purposely compact. It does not describe _all_ the properties - * of the target, only a few key ones. - * - * @see #getDescription() - */ - @Override - public String toString() { - return String.format("AddonTarget %1$s rev %2$d (based on %3$s)", //$NON-NLS-1$ - getVersion(), - getRevision(), - getParent().toString()); - } - - // ---- local methods. - - public void setSkins(@NonNull File[] skins, @NonNull File defaultSkin) { - mDefaultSkin = defaultSkin; - - // we mix the add-on and base platform skins - HashSet skinSet = new HashSet(); - skinSet.addAll(Arrays.asList(skins)); - skinSet.addAll(Arrays.asList(mBasePlatform.getSkins())); - - mSkins = skinSet.toArray(new File[skinSet.size()]); - Arrays.sort(mSkins); - } - - /** - * Sets the USB vendor id in the add-on. - */ - public void setUsbVendorId(int vendorId) { - if (vendorId == 0) { - throw new IllegalArgumentException( "VendorId must be > 0"); - } - - mVendorId = vendorId; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/MissingTarget.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/MissingTarget.java deleted file mode 100644 index 4454040d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/MissingTarget.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2015 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.internal.androidTarget; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SdkVersionInfo; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.io.File; -import java.util.List; -import java.util.Map; - -/** - * A target that we don't have, but is referenced (e.g. by a system image). - */ -public class MissingTarget implements IAndroidTarget { - - private final String mVendor; - - private final AndroidVersion mVersion; - - private final List mSystemImages = Lists.newArrayList(); - - private final String mName; - - public MissingTarget(String vendor, String name, AndroidVersion version) { - mVendor = vendor; - mVersion = version; - mName = name; - } - - @Override - public String getLocation() { - return null; - } - - @Override - public String getVendor() { - return mVendor; - } - - @Override - public String getName() { - return mName; - } - - @Override - public String getFullName() { - return getName(); - } - - @Override - public String getClasspathName() { - return null; - } - - @Override - public String getShortClasspathName() { - return null; - } - - @Override - public String getDescription() { - return null; - } - - @NonNull - @Override - public AndroidVersion getVersion() { - return mVersion; - } - - @Override - public String getVersionName() { - return SdkVersionInfo.getAndroidName(getVersion().getApiLevel()); - } - - @Override - public int getRevision() { - return 0; - } - - @Override - public boolean isPlatform() { - return mVendor == null; - } - - @Override - public IAndroidTarget getParent() { - return null; - } - - @Override - public String getPath(int pathId) { - return null; - } - - @Override - public File getFile(int pathId) { - return null; - } - - @Override - public BuildToolInfo getBuildToolInfo() { - return null; - } - - @NonNull - @Override - public List getBootClasspath() { - return ImmutableList.of(); - } - - @NonNull - @Override - public List getOptionalLibraries() { - return ImmutableList.of(); - } - - @NonNull - @Override - public List getAdditionalLibraries() { - return ImmutableList.of(); - } - - @Override - public boolean hasRenderingLibrary() { - return false; - } - - @NonNull - @Override - public File[] getSkins() { - return new File[0]; - } - - @Nullable - @Override - public File getDefaultSkin() { - return null; - } - - @Override - public String[] getPlatformLibraries() { - return new String[0]; - } - - @Override - public String getProperty(String name) { - return null; - } - - @Override - public Integer getProperty(String name, Integer defaultValue) { - return null; - } - - @Override - public Boolean getProperty(String name, Boolean defaultValue) { - return null; - } - - @Override - public Map getProperties() { - return null; - } - - @Override - public int getUsbVendorId() { - return 0; - } - - @Override - public ISystemImage[] getSystemImages() { - return mSystemImages.toArray(new ISystemImage[mSystemImages.size()]); - } - - public void addSystemImage(ISystemImage image) { - mSystemImages.add(image); - } - - @Nullable - @Override - public ISystemImage getSystemImage(@NonNull IdDisplay tag, @NonNull String abiType) { - for (ISystemImage image : mSystemImages) { - if (tag.equals(image.getTag()) && abiType.equals(image.getAbiType())) { - return image; - } - } - return null; - } - - @Override - public boolean canRunOn(IAndroidTarget target) { - return false; - } - - @Override - public String hashString() { - return AndroidTargetHash.getTargetHashString(this); - } - - @Override - public int compareTo(IAndroidTarget o) { - return 0; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof MissingTarget)) { - return false; - } - MissingTarget other = (MissingTarget) obj; - return Objects.equal(mVendor, other.mVendor) && Objects.equal(mVersion, other.mVersion); - } - - @Override - public int hashCode() { - return Objects.hashCode(mVendor, mVersion); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/OptionalLibraryImpl.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/OptionalLibraryImpl.java deleted file mode 100644 index 97f7efff..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/OptionalLibraryImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015 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.internal.androidTarget; - -import com.android.annotations.NonNull; -import com.android.sdklib.IAndroidTarget; - -import java.io.File; - -/** - * Internal implementation of OptionalLibrary - */ -public class OptionalLibraryImpl implements IAndroidTarget.OptionalLibrary { - - @NonNull - private final String mLibraryName; - @NonNull - private final File mJarFile; - @NonNull - private final String mDescription; - private final boolean mRequireManifestEntry; - - public OptionalLibraryImpl( - @NonNull String libraryName, - @NonNull File jarFile, - @NonNull String description, - boolean requireManifestEntry) { - mLibraryName = libraryName; - mJarFile = jarFile; - mDescription = description; - mRequireManifestEntry = requireManifestEntry; - } - - @Override - @NonNull - public String getName() { - return mLibraryName; - } - - @Override - @NonNull - public File getJar() { - return mJarFile; - } - - @Override - @NonNull - public String getDescription() { - return mDescription; - } - - @Override - public boolean isManifestEntryRequired() { - return mRequireManifestEntry; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/PlatformTarget.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/PlatformTarget.java deleted file mode 100644 index cdd5a9ec..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/androidTarget/PlatformTarget.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * 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.internal.androidTarget; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SdkManager.LayoutlibVersion; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.utils.SparseArray; -import com.google.common.collect.ImmutableList; - -import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Represents a platform target in the SDK. - */ -public final class PlatformTarget implements IAndroidTarget { - - private static final String PLATFORM_VENDOR = "Android Open Source Project"; - - private static final String PLATFORM_NAME = "Android %s"; - private static final String PLATFORM_NAME_PREVIEW = "Android %s (Preview)"; - - /** the OS path to the root folder of the platform component. */ - private final String mRootFolderOsPath; - private final String mName; - private final AndroidVersion mVersion; - private final String mVersionName; - private final int mRevision; - private final Map mProperties; - private final SparseArray mPaths = new SparseArray(); - private File[] mSkins; - private final ISystemImage[] mSystemImages; - private final List mOptionalLibraries; - private final LayoutlibVersion mLayoutlibVersion; - private final BuildToolInfo mBuildToolInfo; - - /** - * Creates a Platform target. - * - * @param sdkOsPath the root folder of the SDK - * @param platformOSPath the root folder of the platform component - * @param apiVersion the API Level + codename. - * @param versionName the version name of the platform. - * @param revision the revision of the platform component. - * @param layoutlibVersion The {@link LayoutlibVersion}. May be null. - * @param systemImages list of supported system images - * @param properties the platform properties - */ - public PlatformTarget( - String sdkOsPath, - String platformOSPath, - AndroidVersion apiVersion, - String versionName, - int revision, - LayoutlibVersion layoutlibVersion, - ISystemImage[] systemImages, - Map properties, - List optionalLibraries, - @NonNull BuildToolInfo buildToolInfo) { - if (!platformOSPath.endsWith(File.separator)) { - platformOSPath = platformOSPath + File.separator; - } - mRootFolderOsPath = platformOSPath; - mProperties = Collections.unmodifiableMap(properties); - mVersion = apiVersion; - mVersionName = versionName; - mRevision = revision; - mLayoutlibVersion = layoutlibVersion; - mBuildToolInfo = buildToolInfo; - mSystemImages = systemImages == null ? new ISystemImage[0] : systemImages; - Arrays.sort(mSystemImages); - mOptionalLibraries = ImmutableList.copyOf(optionalLibraries); - - if (mVersion.isPreview()) { - mName = String.format(PLATFORM_NAME_PREVIEW, mVersionName); - } else { - mName = String.format(PLATFORM_NAME, mVersionName); - } - - // pre-build the path to the platform components - mPaths.put(ANDROID_JAR, mRootFolderOsPath + SdkConstants.FN_FRAMEWORK_LIBRARY); - mPaths.put(UI_AUTOMATOR_JAR, mRootFolderOsPath + SdkConstants.FN_UI_AUTOMATOR_LIBRARY); - mPaths.put(SOURCES, mRootFolderOsPath + SdkConstants.FD_ANDROID_SOURCES); - mPaths.put(ANDROID_AIDL, mRootFolderOsPath + SdkConstants.FN_FRAMEWORK_AIDL); - mPaths.put(SAMPLES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_SAMPLES_FOLDER); - mPaths.put(SKINS, mRootFolderOsPath + SdkConstants.OS_SKINS_FOLDER); - mPaths.put(TEMPLATES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_TEMPLATES_FOLDER); - mPaths.put(DATA, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER); - mPaths.put(ATTRIBUTES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_ATTRS_XML); - mPaths.put(MANIFEST_ATTRIBUTES, - mRootFolderOsPath + SdkConstants.OS_PLATFORM_ATTRS_MANIFEST_XML); - mPaths.put(RESOURCES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_RESOURCES_FOLDER); - mPaths.put(FONTS, mRootFolderOsPath + SdkConstants.OS_PLATFORM_FONTS_FOLDER); - mPaths.put(LAYOUT_LIB, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_LAYOUTLIB_JAR); - mPaths.put(WIDGETS, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_WIDGETS); - mPaths.put(ACTIONS_ACTIVITY, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_INTENT_ACTIONS_ACTIVITY); - mPaths.put(ACTIONS_BROADCAST, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_INTENT_ACTIONS_BROADCAST); - mPaths.put(ACTIONS_SERVICE, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_INTENT_ACTIONS_SERVICE); - mPaths.put(CATEGORIES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_DATA_FOLDER + - SdkConstants.FN_INTENT_CATEGORIES); - mPaths.put(ANT, mRootFolderOsPath + SdkConstants.OS_PLATFORM_ANT_FOLDER); - } - - /** - * Returns the {@link LayoutlibVersion}. May be null. - */ - public LayoutlibVersion getLayoutlibVersion() { - return mLayoutlibVersion; - } - - @Override - @Nullable - public ISystemImage getSystemImage(@NonNull IdDisplay tag, @NonNull String abiType) { - for (ISystemImage sysImg : mSystemImages) { - if (sysImg.getTag().equals(tag) && sysImg.getAbiType().equals(abiType)) { - return sysImg; - } - } - return null; - } - - @Override - public ISystemImage[] getSystemImages() { - return mSystemImages; - } - - @Override - public String getLocation() { - return mRootFolderOsPath; - } - - /** - * {@inheritDoc} - *

- * For Platform, the vendor name is always "Android". - * - * @see com.android.sdklib.IAndroidTarget#getVendor() - */ - @Override - public String getVendor() { - return PLATFORM_VENDOR; - } - - @Override - public String getName() { - return mName; - } - - @Override - public String getFullName() { - return mName; - } - - @Override - public String getClasspathName() { - return mName; - } - - @Override - public String getShortClasspathName() { - return mName; - } - - /* - * (non-Javadoc) - * - * Description for the Android platform is dynamically generated. - * - * @see com.android.sdklib.IAndroidTarget#getDescription() - */ - @Override - public String getDescription() { - return String.format("Standard Android platform %s", mVersionName); - } - - @NonNull - @Override - public AndroidVersion getVersion() { - return mVersion; - } - - @Override - public String getVersionName() { - return mVersionName; - } - - @Override - public int getRevision() { - return mRevision; - } - - @Override - public boolean isPlatform() { - return true; - } - - @Override - public IAndroidTarget getParent() { - return null; - } - - @Override - public String getPath(int pathId) { - return mPaths.get(pathId); - } - - @Override - public File getFile(int pathId) { - return new File(getPath(pathId)); - } - - @Override - public BuildToolInfo getBuildToolInfo() { - return mBuildToolInfo; - } - - @Override @NonNull - public List getBootClasspath() { - return ImmutableList.of(getPath(IAndroidTarget.ANDROID_JAR)); - } - - @NonNull - @Override - public List getOptionalLibraries() { - return mOptionalLibraries; - } - - /** - * Always returns null, as a standard platform has no additional libraries. - * - * {@inheritDoc} - * @see com.android.sdklib.IAndroidTarget#getAdditionalLibraries() - */ - @NonNull - @Override - public List getAdditionalLibraries() { - return ImmutableList.of(); - } - - /** - * Returns whether the target is able to render layouts. This is always true for platforms. - */ - @Override - public boolean hasRenderingLibrary() { - return true; - } - - @NonNull - @Override - public File[] getSkins() { - return mSkins; - } - - @Nullable - @Override - public File getDefaultSkin() { - // only one skin? easy. - if (mSkins.length == 1) { - return mSkins[0]; - } - - // look for the skin name in the platform props - String skinName = mProperties.get(SdkConstants.PROP_SDK_DEFAULT_SKIN); - if (skinName == null) { - // otherwise try to find a good default. - if (mVersion.getApiLevel() >= 4) { - // at this time, this is the default skin for all older platforms that had 2+ skins. - skinName = "WVGA800"; //$NON-NLS-1$ - } else { - skinName = "HVGA"; // this is for 1.5 and earlier. //$NON-NLS-1$ - } - } - - return new File(getFile(IAndroidTarget.SKINS), skinName); - } - - /** - * Currently always return a fixed list with "android.test.runner" in it. - *

- * TODO change the fixed library list to be build-dependent later. - * {@inheritDoc} - */ - @Override - public String[] getPlatformLibraries() { - return new String[] { SdkConstants.ANDROID_TEST_RUNNER_LIB }; - } - - /** - * The platform has no USB Vendor Id: always return {@link IAndroidTarget#NO_USB_ID}. - * {@inheritDoc} - */ - @Override - public int getUsbVendorId() { - return NO_USB_ID; - } - - @Override - public boolean canRunOn(IAndroidTarget target) { - // basic test - if (target == this) { - return true; - } - - // if the platform has a codename (ie it's a preview of an upcoming platform), then - // both platforms must be exactly identical. - if (mVersion.getCodename() != null) { - return mVersion.equals(target.getVersion()); - } - - // target is compatible wit the receiver as long as its api version number is greater or - // equal. - return target.getVersion().getApiLevel() >= mVersion.getApiLevel(); - } - - @Override - public String hashString() { - return AndroidTargetHash.getPlatformHashString(mVersion); - } - - @Override - public int hashCode() { - return hashString().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PlatformTarget) { - PlatformTarget platform = (PlatformTarget)obj; - - return mVersion.equals(platform.getVersion()); - } - - return false; - } - - /* - * Order by API level (preview/n count as between n and n+1). - * At the same API level, order as: Platform first, then add-on ordered by vendor and then name - * (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - @Override - public int compareTo(IAndroidTarget target) { - // quick check. - if (this == target) { - return 0; - } - - int versionDiff = mVersion.compareTo(target.getVersion()); - - // only if the version are the same do we care about add-ons. - if (versionDiff == 0) { - // platforms go before add-ons. - if (target.isPlatform() == false) { - return -1; - } - } - - return versionDiff; - } - - /** - * Returns a string representation suitable for debugging. - * The representation is not intended for display to the user. - * - * The representation is also purposely compact. It does not describe _all_ the properties - * of the target, only a few key ones. - * - * @see #getDescription() - */ - @Override - public String toString() { - return String.format("PlatformTarget %1$s rev %2$d", //$NON-NLS-1$ - getVersion(), - getRevision()); - } - - @Override - public String getProperty(String name) { - return mProperties.get(name); - } - - @Override - public Integer getProperty(String name, Integer defaultValue) { - try { - String value = getProperty(name); - if (value != null) { - return Integer.decode(value); - } - } catch (NumberFormatException e) { - // ignore, return default value; - } - - return defaultValue; - } - - @Override - public Boolean getProperty(String name, Boolean defaultValue) { - String value = getProperty(name); - if (value != null) { - return Boolean.valueOf(value); - } - - return defaultValue; - } - - @Override - public Map getProperties() { - return mProperties; // mProperties is unmodifiable. - } - - // ---- platform only methods. - - public void setSkins(@NonNull File[] skins) { - mSkins = skins; - Arrays.sort(mSkins); - } - - public void setSamplesPath(String osLocation) { - mPaths.put(SAMPLES, osLocation); - } - - public void setSourcesPath(String osLocation) { - mPaths.put(SOURCES, osLocation); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdInfo.java deleted file mode 100644 index 1c682b32..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdInfo.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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.internal.avd; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SystemImage; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.devices.Device; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.google.common.base.Charsets; -import com.google.common.io.Files; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.Map; - -/** - * An immutable structure describing an Android Virtual Device. - */ -public final class AvdInfo implements Comparable { - - /** - * Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid. - */ - public enum AvdStatus { - /** No error */ - OK, - /** Missing 'path' property in the ini file */ - ERROR_PATH, - /** Missing config.ini file in the AVD data folder */ - ERROR_CONFIG, - /** Missing 'target' property in the ini file */ - ERROR_TARGET_HASH, - /** Target was not resolved from its hash */ - ERROR_TARGET, - /** Unable to parse config.ini */ - ERROR_PROPERTIES, - /** System Image folder in config.ini doesn't exist */ - ERROR_IMAGE_DIR, - /** The {@link Device} this AVD is based on has changed from its original configuration*/ - ERROR_DEVICE_CHANGED, - /** The {@link Device} this AVD is based on is no longer available */ - ERROR_DEVICE_MISSING, - /** the {@link SystemImage} this AVD is based on is no longer available */ - ERROR_IMAGE_MISSING - } - - private final String mName; - private final File mIniFile; - private final String mFolderPath; - private final String mTargetHash; - private final IAndroidTarget mTarget; - private final String mAbiType; - /** An immutable map of properties. This must not be modified. Map can be empty. Never null. */ - private final Map mProperties; - private final AvdStatus mStatus; - private final IdDisplay mTag; - - /** - * Creates a new valid AVD info. Values are immutable. - *

- * Such an AVD is available and can be used. - * The error string is set to null. - * - * @param name The name of the AVD (for display or reference) - * @param iniFile The path to the config.ini file - * @param folderPath The path to the data directory - * @param targetHash the target hash - * @param target The target. Can be null, if the target was not resolved. - * @param tag The tag id/display. - * @param abiType Name of the abi. - * @param properties The property map. If null, an empty map will be created. - */ - public AvdInfo(@NonNull String name, - @NonNull File iniFile, - @NonNull String folderPath, - @NonNull String targetHash, - @Nullable IAndroidTarget target, - @NonNull IdDisplay tag, - @NonNull String abiType, - @Nullable Map properties) { - this(name, iniFile, folderPath, - targetHash, target, tag, abiType, - properties, AvdStatus.OK); - } - - /** - * Creates a new invalid AVD info. Values are immutable. - *

- * Such an AVD is not complete and cannot be used. - * The error string must be non-null. - * - * @param name The name of the AVD (for display or reference) - * @param iniFile The path to the config.ini file - * @param folderPath The path to the data directory - * @param targetHash the target hash - * @param target The target. Can be null, if the target was not resolved. - * @param tag The tag id/display. - * @param abiType Name of the abi. - * @param properties The property map. If null, an empty map will be created. - * @param status The {@link AvdStatus} of this AVD. Cannot be null. - */ - public AvdInfo(@NonNull String name, - @NonNull File iniFile, - @NonNull String folderPath, - @NonNull String targetHash, - @Nullable IAndroidTarget target, - @NonNull IdDisplay tag, - @NonNull String abiType, - @Nullable Map properties, - @NonNull AvdStatus status) { - mName = name; - mIniFile = iniFile; - mFolderPath = folderPath; - mTargetHash = targetHash; - mTarget = target; - mTag = tag; - mAbiType = abiType; - mProperties = properties == null ? Collections.emptyMap() - : Collections.unmodifiableMap(properties); - mStatus = status; - } - - /** Returns the name of the AVD. */ - @NonNull - public String getName() { - return mName; - } - - /** Returns the path of the AVD data directory. */ - @NonNull - public String getDataFolderPath() { - return mFolderPath; - } - - /** Returns the tag id/display of the AVD. */ - @NonNull - public IdDisplay getTag() { - return mTag; - } - - /** Returns the processor type of the AVD. */ - @NonNull - public String getAbiType() { - return mAbiType; - } - - @NonNull - public String getCpuArch() { - String cpuArch = mProperties.get(AvdManager.AVD_INI_CPU_ARCH); - if (cpuArch != null) { - return cpuArch; - } - - // legacy - return SdkConstants.CPU_ARCH_ARM; - } - - @NonNull - public String getDeviceManufacturer() { - String deviceManufacturer = mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); - if (deviceManufacturer != null && !deviceManufacturer.isEmpty()) { - return deviceManufacturer; - } - - return ""; // $NON-NLS-1$ - } - - @NonNull - public String getDeviceName() { - String deviceName = mProperties.get(AvdManager.AVD_INI_DEVICE_NAME); - if (deviceName != null && !deviceName.isEmpty()) { - return deviceName; - } - - return ""; // $NON-NLS-1$ - } - - /** Convenience function to return a more user friendly name of the abi type. */ - @NonNull - public static String getPrettyAbiType(@NonNull AvdInfo avdInfo) { - return getPrettyAbiType(avdInfo.getTag(), avdInfo.getAbiType()); - } - - /** Convenience function to return a more user friendly name of the abi type. */ - @NonNull - public static String getPrettyAbiType(@NonNull ISystemImage sysImg) { - return getPrettyAbiType(sysImg.getTag(), sysImg.getAbiType()); - } - - /** Convenience function to return a more user friendly name of the abi type. */ - @NonNull - public static String getPrettyAbiType(@NonNull IdDisplay tag, @NonNull String rawAbi) { - String s = ""; // $NON-NLS-1$ - - if (!SystemImage.DEFAULT_TAG.equals(tag)) { - s = tag.getDisplay() + ' '; - } - - Abi abi = Abi.getEnum(rawAbi); - s += (abi == null ? rawAbi : abi.getDisplayName()) + " (" + rawAbi + ')'; - - return s; - } - - /** - * Returns the target hash string. - */ - @NonNull - public String getTargetHash() { - return mTargetHash; - } - - /** Returns the target of the AVD, or null if it has not been resolved. */ - @Nullable - public IAndroidTarget getTarget() { - return mTarget; - } - - /** Returns the {@link AvdStatus} of the receiver. */ - @NonNull - public AvdStatus getStatus() { - return mStatus; - } - - /** - * Helper method that returns the default AVD folder that would be used for a given - * AVD name if and only if the AVD was created with the default choice. - *

- * Callers must NOT use this to "guess" the actual folder from an actual AVD since - * the purpose of the AVD .ini file is to be able to change this folder. Callers - * should however use this to create a new {@link AvdInfo} to setup its data folder - * to the default. - *

- * The default is {@code getDefaultAvdFolder()/avdname.avd/}. - *

- * For an actual existing AVD, callers must use {@link #getDataFolderPath()} instead. - * - * @param manager The AVD Manager, used to get the AVD storage path. - * @param avdName The name of the desired AVD. - * @param unique Whether to return the default or a unique variation of the default. - * @throws AndroidLocationException if there's a problem getting android root directory. - */ - @NonNull - public static File getDefaultAvdFolder(@NonNull AvdManager manager, @NonNull String avdName, - boolean unique) - throws AndroidLocationException { - String base = manager.getBaseAvdFolder(); - File result = new File(base, avdName + AvdManager.AVD_FOLDER_EXTENSION); - if (unique) { - int suffix = 0; - while (result.exists()) { - result = new File(base, String.format("%s_%d%s", avdName, (++suffix), - AvdManager.AVD_FOLDER_EXTENSION)); - } - } - return result; - } - - /** Compatibility forwarding until the usages in tools/swt are updated */ - @Deprecated - @NonNull - public static File getDefaultAvdFolder(@NonNull AvdManager manager, @NonNull String avdName) - throws AndroidLocationException{ - return getDefaultAvdFolder(manager, avdName, false); - } - - /** - * Helper method that returns the .ini {@link File} for a given AVD name. - *

- * The default is {@code getDefaultAvdFolder()/avdname.ini}. - * - * @param manager The AVD Manager, used to get the AVD storage path. - * @param avdName The name of the desired AVD. - * @throws AndroidLocationException if there's a problem getting android root directory. - */ - @NonNull - public static File getDefaultIniFile(@NonNull AvdManager manager, @NonNull String avdName) - throws AndroidLocationException { - String avdRoot = manager.getBaseAvdFolder(); - return new File(avdRoot, avdName + AvdManager.INI_EXTENSION); - } - - /** - * Returns the .ini {@link File} for this AVD. - */ - @NonNull - public File getIniFile() { - return mIniFile; - } - - /** - * Helper method that returns the Config {@link File} for a given AVD name. - */ - @NonNull - public static File getConfigFile(@NonNull String path) { - return new File(path, AvdManager.CONFIG_INI); - } - - /** - * Returns the Config {@link File} for this AVD. - */ - @NonNull - public File getConfigFile() { - return getConfigFile(mFolderPath); - } - - /** - * Returns an unmodifiable map of properties for the AVD. - * This can be empty but not null. - * Callers must NOT try to modify this immutable map. - */ - @NonNull - public Map getProperties() { - return mProperties; - } - - /** - * Returns the error message for the AVD or null if {@link #getStatus()} - * returns {@link AvdStatus#OK} - */ - @Nullable - public String getErrorMessage() { - switch (mStatus) { - case ERROR_PATH: - return String.format("Missing AVD 'path' property in %1$s", getIniFile()); - case ERROR_CONFIG: - return String.format("Missing config.ini file in %1$s", mFolderPath); - case ERROR_TARGET_HASH: - return String.format("Missing 'target' property in %1$s", getIniFile()); - case ERROR_TARGET: - return String.format("Unknown target '%1$s' in %2$s", - mTargetHash, getIniFile()); - case ERROR_PROPERTIES: - return String.format("Failed to parse properties from %1$s", - getConfigFile()); - case ERROR_IMAGE_DIR: - return String.format( - "Missing system image for %1$s%2$s %3$s. Run 'android update avd -n %4$s'", - SystemImage.DEFAULT_TAG.equals(mTag) ? "" : (mTag.getDisplay() + " "), - mAbiType, - mTarget.getFullName(), - mName); - case ERROR_DEVICE_CHANGED: - return String.format("%1$s %2$s configuration has changed since AVD creation", - mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER), - mProperties.get(AvdManager.AVD_INI_DEVICE_NAME)); - case ERROR_DEVICE_MISSING: - return String.format("%1$s %2$s no longer exists as a device", - mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER), - mProperties.get(AvdManager.AVD_INI_DEVICE_NAME)); - case OK: - assert false; - return null; - } - - return null; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the Object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - */ - @Override - public int compareTo(AvdInfo o) { - // first handle possible missing targets (if the AVD failed to load for unresolved targets) - if (mTarget == null && o != null && o.mTarget == null) { - return 0; - } if (mTarget == null) { - return +1; - } else if (o == null || o.mTarget == null) { - return -1; - } - - // then compare the targets - int targetDiff = mTarget.compareTo(o.mTarget); - - if (targetDiff == 0) { - // same target? compare on the avd name - return mName.compareTo(o.mName); - } - - return targetDiff; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdManager.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdManager.java deleted file mode 100644 index 11e6bbb5..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/AvdManager.java +++ /dev/null @@ -1,2196 +0,0 @@ -/* - * 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.internal.avd; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.io.FileWrapper; -import com.android.io.IAbstractFile; -import com.android.io.StreamException; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SdkManager; -import com.android.sdklib.SystemImage; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.devices.DeviceManager.DeviceStatus; -import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.local.LocalSdk; -import com.android.sdklib.repository.local.LocalSysImgPkgInfo; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; -import com.android.utils.ILogger; -import com.android.utils.NullLogger; -import com.android.utils.Pair; -import com.google.common.base.Charsets; -import com.google.common.io.Closeables; -import com.google.common.io.Files; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Android Virtual Device Manager to manage AVDs. - */ -public class AvdManager { - - /** - * Exception thrown when something is wrong with a target path. - */ - private static final class InvalidTargetPathException extends Exception { - private static final long serialVersionUID = 1L; - - InvalidTargetPathException(String message) { - super(message); - } - } - - private static final Pattern INI_LINE_PATTERN = - Pattern.compile("^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); //$NON-NLS-1$ - - public static final String AVD_FOLDER_EXTENSION = ".avd"; //$NON-NLS-1$ - - /** Charset encoding used by the avd.ini/config.ini. */ - public static final String AVD_INI_ENCODING = "avd.ini.encoding"; //$NON-NLS-1$ - - /** - * The *absolute* path to the AVD folder (which contains the #CONFIG_INI file). - */ - public static final String AVD_INFO_ABS_PATH = "path"; //$NON-NLS-1$ - - /** - * The path to the AVD folder (which contains the #CONFIG_INI file) relative to - * the {@link AndroidLocation#FOLDER_DOT_ANDROID}. This information is written - * in the avd ini only if the AVD folder is located under the .android path - * (that is the relative that has no backward {@code ..} references). - */ - public static final String AVD_INFO_REL_PATH = "path.rel"; //$NON-NLS-1$ - - /** - * The {@link IAndroidTarget#hashString()} of the AVD. - */ - public static final String AVD_INFO_TARGET = "target"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the tag id of the specific avd - */ - public static final String AVD_INI_TAG_ID = "tag.id"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the tag display of the specific avd - */ - public static final String AVD_INI_TAG_DISPLAY = "tag.display"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the abi type of the specific avd - */ - public static final String AVD_INI_ABI_TYPE = "abi.type"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the CPU architecture of the specific avd - */ - public static final String AVD_INI_CPU_ARCH = "hw.cpu.arch"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the CPU architecture of the specific avd - */ - public static final String AVD_INI_CPU_MODEL = "hw.cpu.model"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the manufacturer of the device this avd was based on. - */ - public static final String AVD_INI_DEVICE_MANUFACTURER = "hw.device.manufacturer"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the name of the device this avd was based on. - */ - public static final String AVD_INI_DEVICE_NAME = "hw.device.name"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the SDK-relative path of the skin folder, if any, - * or a 320x480 like constant for a numeric skin size. - * - * @see #NUMERIC_SKIN_SIZE - */ - public static final String AVD_INI_SKIN_PATH = "skin.path"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the SDK-relative path of the skin folder to be selected if - * skins for this device become enabled. - */ - public static final String AVD_INI_BACKUP_SKIN_PATH = "skin.path.backup"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing an UI name for the skin. - * This config key is ignored by the emulator. It is only used by the SDK manager or - * tools to give a friendlier name to the skin. - * If missing, use the {@link #AVD_INI_SKIN_PATH} key instead. - */ - public static final String AVD_INI_SKIN_NAME = "skin.name"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing whether a dynamic skin should be displayed. - */ - public static final String AVD_INI_SKIN_DYNAMIC = "skin.dynamic"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the path to the sdcard file. - * If missing, the default name "sdcard.img" will be used for the sdcard, if there's such - * a file. - * - * @see #SDCARD_IMG - */ - public static final String AVD_INI_SDCARD_PATH = "sdcard.path"; //$NON-NLS-1$ - /** - * AVD/config.ini key name representing the size of the SD card. - * This property is for UI purposes only. It is not used by the emulator. - * - * @see #SDCARD_SIZE_PATTERN - * @see #parseSdcardSize(String, String[]) - */ - public static final String AVD_INI_SDCARD_SIZE = "sdcard.size"; //$NON-NLS-1$ - /** - * AVD/config.ini key name representing the first path where the emulator looks - * for system images. Typically this is the path to the add-on system image or - * the path to the platform system image if there's no add-on. - *

- * The emulator looks at {@link #AVD_INI_IMAGES_1} before {@link #AVD_INI_IMAGES_2}. - */ - public static final String AVD_INI_IMAGES_1 = "image.sysdir.1"; //$NON-NLS-1$ - /** - * AVD/config.ini key name representing the second path where the emulator looks - * for system images. Typically this is the path to the platform system image. - * - * @see #AVD_INI_IMAGES_1 - */ - public static final String AVD_INI_IMAGES_2 = "image.sysdir.2"; //$NON-NLS-1$ - /** - * AVD/config.ini key name representing the presence of the snapshots file. - * This property is for UI purposes only. It is not used by the emulator. - * - * @see #SNAPSHOTS_IMG - */ - public static final String AVD_INI_SNAPSHOT_PRESENT = "snapshot.present"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing whether hardware OpenGLES emulation is enabled - */ - public static final String AVD_INI_GPU_EMULATION = "hw.gpu.enabled"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing how to emulate the front facing camera - */ - public static final String AVD_INI_CAMERA_FRONT = "hw.camera.front"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing how to emulate the rear facing camera - */ - public static final String AVD_INI_CAMERA_BACK = "hw.camera.back"; //$NON-NLS-1$ - - /** - * AVD/config.ini key name representing the amount of RAM the emulated device should have - */ - public static final String AVD_INI_RAM_SIZE = "hw.ramSize"; - - /** - * AVD/config.ini key name representing the amount of memory available to applications by default - */ - public static final String AVD_INI_VM_HEAP_SIZE = "vm.heapSize"; - - /** - * AVD/config.ini key name representing the size of the data partition - */ - public static final String AVD_INI_DATA_PARTITION_SIZE = "disk.dataPartition.size"; - - /** - * AVD/config.ini key name representing the hash of the device this AVD is based on.
- * This old hash is deprecated and shouldn't be used anymore. - * It represents the Device.hashCode() and is not stable accross implementations. - * @see #AVD_INI_DEVICE_HASH_V2 - */ - public static final String AVD_INI_DEVICE_HASH_V1 = "hw.device.hash"; - - /** - * AVD/config.ini key name representing the hash of the device hardware properties - * actually present in the config.ini. This replaces {@link #AVD_INI_DEVICE_HASH_V1}. - *

- * To find this hash, use - * {@code DeviceManager.getHardwareProperties(device).get(AVD_INI_DEVICE_HASH_V2)}. - */ - public static final String AVD_INI_DEVICE_HASH_V2 = "hw.device.hash2"; - - /** - * Pattern to match pixel-sized skin "names", e.g. "320x480". - */ - public static final Pattern NUMERIC_SKIN_SIZE = Pattern.compile("([0-9]{2,})x([0-9]{2,})"); //$NON-NLS-1$ - - private static final String USERDATA_IMG = "userdata.img"; //$NON-NLS-1$ - private static final String BOOT_PROP = "boot.prop"; //$NON-NLS-1$ - static final String CONFIG_INI = "config.ini"; //$NON-NLS-1$ - private static final String SDCARD_IMG = "sdcard.img"; //$NON-NLS-1$ - private static final String SNAPSHOTS_IMG = "snapshots.img"; //$NON-NLS-1$ - - static final String INI_EXTENSION = ".ini"; //$NON-NLS-1$ - private static final Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\" + //$NON-NLS-1$ - INI_EXTENSION + "$", //$NON-NLS-1$ - Pattern.CASE_INSENSITIVE); - - private static final Pattern IMAGE_NAME_PATTERN = Pattern.compile("(.+)\\.img$", //$NON-NLS-1$ - Pattern.CASE_INSENSITIVE); - - /** - * Pattern for matching SD Card sizes, e.g. "4K" or "16M". - * Callers should use {@link #parseSdcardSize(String, String[])} instead of using this directly. - */ - private static final Pattern SDCARD_SIZE_PATTERN = Pattern.compile("(\\d+)([KMG])"); //$NON-NLS-1$ - - /** - * Minimal size of an SDCard image file in bytes. Currently 9 MiB. - */ - - public static final long SDCARD_MIN_BYTE_SIZE = 9<<20; - /** - * Maximal size of an SDCard image file in bytes. Currently 1023 GiB. - */ - public static final long SDCARD_MAX_BYTE_SIZE = 1023L<<30; - - /** The sdcard string represents a valid number but the size is outside of the allowed range. */ - public static final int SDCARD_SIZE_NOT_IN_RANGE = 0; - /** The sdcard string looks like a size number+suffix but the number failed to decode. */ - public static final int SDCARD_SIZE_INVALID = -1; - /** The sdcard string doesn't look like a size, it might be a path instead. */ - public static final int SDCARD_NOT_SIZE_PATTERN = -2; - - /** Regex used to validate characters that compose an AVD name. */ - public static final Pattern RE_AVD_NAME = Pattern.compile("[a-zA-Z0-9._-]+"); //$NON-NLS-1$ - - /** List of valid characters for an AVD name. Used for display purposes. */ - public static final String CHARS_AVD_NAME = "a-z A-Z 0-9 . _ -"; //$NON-NLS-1$ - - public static final String HARDWARE_INI = "hardware.ini"; //$NON-NLS-1$ - - /** - * Status returned by {@link AvdManager#isAvdNameConflicting(String)}. - */ - public enum AvdConflict { - /** There is no known conflict for the given AVD name. */ - NO_CONFLICT, - /** The AVD name conflicts with an existing valid AVD. */ - CONFLICT_EXISTING_AVD, - /** The AVD name conflicts with an existing invalid AVD. */ - CONFLICT_INVALID_AVD, - /** - * The AVD name does not conflict with any known AVD however there are - * files or directory that would cause a conflict if this were to be created. - */ - CONFLICT_EXISTING_PATH, - } - - // A map where the keys are the locations of the SDK and the values are the corresponding - // AvdManagers. This prevents us from creating multiple AvdManagers for the same SDK and having - // them get out of sync. - private static final Map mManagers = - Collections.synchronizedMap(new WeakHashMap()); - - private final ArrayList mAllAvdList = new ArrayList(); - private AvdInfo[] mValidAvdList; - private AvdInfo[] mBrokenAvdList; - private final LocalSdk myLocalSdk; - private final Map myDeviceManagers = - new HashMap(); - - /** - * Creates an AVD Manager for a given SDK represented by a {@link LocalSdk}. - * @param localSdk The SDK. - * @param log The log object to receive the log of the initial loading of the AVDs. - * This log object is not kept by this instance of AvdManager and each - * method takes its own logger. The rationale is that the AvdManager - * might be called from a variety of context, each with different - * logging needs. Cannot be null. - * @throws AndroidLocationException - */ - protected AvdManager(@NonNull LocalSdk localSdk, @NonNull ILogger log) - throws AndroidLocationException { - myLocalSdk = localSdk; - buildAvdList(mAllAvdList, log); - } - - /** - * Returns an AVD Manager for a given SDK represented by a {@link LocalSdk}. - * One AVD Manager instance is created by SDK location and then cached and reused. - * - * @param localSdk The SDK. - * @param log The log object to receive the log of the initial loading of the AVDs. - * This log object is not kept by this instance of AvdManager and each - * method takes its own logger. The rationale is that the AvdManager - * might be called from a variety of context, each with different - * logging needs. Cannot be null. - * @throws AndroidLocationException - */ - @NonNull - public static AvdManager getInstance(@NonNull LocalSdk localSdk, @NonNull ILogger log) - throws AndroidLocationException { - synchronized(mManagers) { - AvdManager manager; - if ((manager = mManagers.get(localSdk.getLocation().getPath())) != null) { - return manager; - } - manager = new AvdManager(localSdk, log); - - mManagers.put(localSdk.getLocation().getPath(), manager); - return manager; - } - } - - /** - * Returns the base folder where AVDs are created. - * - * @throws AndroidLocationException - */ - @NonNull - public String getBaseAvdFolder() throws AndroidLocationException { - assert AndroidLocation.getFolder().endsWith(File.separator); - return AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD; - } - - /** - * Returns the {@link LocalSdk} associated with the {@link AvdManager}. - */ - @NonNull - public LocalSdk getLocalSdk() { - return myLocalSdk; - } - - /** - * Returns the {@link SdkManager} associated with the {@link AvdManager}. - * Note: This is temporary and will be removed as SdkManager is phased out. - * TODO: Remove this when SdkManager is removed - */ - @NonNull - @Deprecated - public SdkManager getSdkManager() { - return SdkManager.createManager(myLocalSdk.getPath(), NullLogger.getLogger()); - } - - /** - * Parse the sdcard string to decode the size. - * Returns: - *

    - *
  • The size in bytes > 0 if the sdcard string is a valid size in the allowed range. - *
  • {@link #SDCARD_SIZE_NOT_IN_RANGE} (0) - * if the sdcard string is a valid size NOT in the allowed range. - *
  • {@link #SDCARD_SIZE_INVALID} (-1) - * if the sdcard string is number that fails to parse correctly. - *
  • {@link #SDCARD_NOT_SIZE_PATTERN} (-2) - * if the sdcard string is not a number, in which case it's probably a file path. - *
- * - * @param sdcard The sdcard string, which can be a file path, a size string or something else. - * @param parsedStrings If non-null, an array of 2 strings. The first string will be - * filled with the parsed numeric size and the second one will be filled with the - * parsed suffix. This is filled even if the returned size is deemed out of range or - * failed to parse. The values are null if the sdcard is not a size pattern. - * @return A size in byte if > 0, or {@link #SDCARD_SIZE_NOT_IN_RANGE}, - * {@link #SDCARD_SIZE_INVALID} or {@link #SDCARD_NOT_SIZE_PATTERN} as error codes. - */ - public static long parseSdcardSize(@NonNull String sdcard, @Nullable String[] parsedStrings) { - - if (parsedStrings != null) { - assert parsedStrings.length == 2; - parsedStrings[0] = null; - parsedStrings[1] = null; - } - - Matcher m = SDCARD_SIZE_PATTERN.matcher(sdcard); - if (m.matches()) { - if (parsedStrings != null) { - assert parsedStrings.length == 2; - parsedStrings[0] = m.group(1); - parsedStrings[1] = m.group(2); - } - - // get the sdcard values for checks - try { - long sdcardSize = Long.parseLong(m.group(1)); - - String sdcardSizeModifier = m.group(2); - if ("K".equals(sdcardSizeModifier)) { //$NON-NLS-1$ - sdcardSize <<= 10; - } else if ("M".equals(sdcardSizeModifier)) { //$NON-NLS-1$ - sdcardSize <<= 20; - } else if ("G".equals(sdcardSizeModifier)) { //$NON-NLS-1$ - sdcardSize <<= 30; - } - - if (sdcardSize < SDCARD_MIN_BYTE_SIZE || - sdcardSize > SDCARD_MAX_BYTE_SIZE) { - return SDCARD_SIZE_NOT_IN_RANGE; - } - - return sdcardSize; - } catch (NumberFormatException e) { - // This could happen if the number is too large to fit in a long. - return SDCARD_SIZE_INVALID; - } - } - - return SDCARD_NOT_SIZE_PATTERN; - } - - /** - * Returns all the existing AVDs. - * @return a newly allocated array containing all the AVDs. - */ - @NonNull - public AvdInfo[] getAllAvds() { - synchronized (mAllAvdList) { - return mAllAvdList.toArray(new AvdInfo[mAllAvdList.size()]); - } - } - - /** - * Returns all the valid AVDs. - * @return a newly allocated array containing all valid the AVDs. - */ - @NonNull - public AvdInfo[] getValidAvds() { - synchronized (mAllAvdList) { - if (mValidAvdList == null) { - ArrayList list = new ArrayList(); - for (AvdInfo avd : mAllAvdList) { - if (avd.getStatus() == AvdStatus.OK) { - list.add(avd); - } - } - - mValidAvdList = list.toArray(new AvdInfo[list.size()]); - } - return mValidAvdList; - } - } - - /** - * Returns all the broken AVDs. - * @return a newly allocated array containing all the broken AVDs. - */ - @NonNull - public AvdInfo[] getBrokenAvds() { - synchronized (mAllAvdList) { - if (mBrokenAvdList == null) { - ArrayList list = new ArrayList(); - for (AvdInfo avd : mAllAvdList) { - if (avd.getStatus() != AvdStatus.OK) { - list.add(avd); - } - } - mBrokenAvdList = list.toArray(new AvdInfo[list.size()]); - } - return mBrokenAvdList; - } - } - - /** - * Returns the {@link AvdInfo} matching the given name. - *

- * The search is case-insensitive. - * - * @param name the name of the AVD to return - * @param validAvdOnly if true, only look through the list of valid AVDs. - * @return the matching AvdInfo or null if none were found. - */ - @Nullable - public AvdInfo getAvd(@Nullable String name, boolean validAvdOnly) { - - boolean ignoreCase = SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS; - - if (validAvdOnly) { - for (AvdInfo info : getValidAvds()) { - String name2 = info.getName(); - if (name2.equals(name) || (ignoreCase && name2.equalsIgnoreCase(name))) { - return info; - } - } - } else { - synchronized (mAllAvdList) { - for (AvdInfo info : mAllAvdList) { - String name2 = info.getName(); - if (name2.equals(name) || (ignoreCase && name2.equalsIgnoreCase(name))) { - return info; - } - } - } - } - - return null; - } - - /** - * Returns whether an emulator is currently running the AVD. - */ - public boolean isAvdRunning(@NonNull AvdInfo info) { - try { - String pid = getAvdPid(info); - if (pid != null) { - String command; - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - command = "cmd /c \"tasklist /FI \"PID eq " + pid + "\" | findstr " + pid - + "\""; - } else { - command = "kill -0 " + pid; - } - try { - Process p = Runtime.getRuntime().exec(command); - // If the process ends with non-0 it means the process doesn't exist - return p.waitFor() == 0; - } catch (IOException e) { - // To be safe return true - return true; - } catch (InterruptedException e) { - // To be safe return true - return true; - } - } - } - catch (IOException e) { - // To be safe return true - return true; - } - return false; - } - - public void stopAvd(@NonNull AvdInfo info) { - try { - String pid = getAvdPid(info); - if (pid != null) { - String command; - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - command = "cmd /c \"taskkill /PID " + pid + "\""; - } else { - command = "kill " + pid; - } - try { - Process p = Runtime.getRuntime().exec(command); - // If the process ends with non-0 it means the process doesn't exist - p.waitFor(); - } catch (IOException e) { - } catch (InterruptedException e) { - } - } - } - catch (IOException e) { - } - } - - private String getAvdPid(@NonNull AvdInfo info) throws IOException { - // this is a file on Unix, and a directory on Windows. - File f = new File(info.getDataFolderPath(), "userdata-qemu.img.lock"); //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - f = new File(f, "pid"); - } - if (f.exists()) { - return Files.toString(f, Charsets.UTF_8); - } - return null; - } - - - - /** - * Returns whether this AVD name would generate a conflict. - * - * @param name the name of the AVD to return - * @return A pair of {@link AvdConflict} and the path or AVD name that conflicts. - */ - @NonNull - public Pair isAvdNameConflicting(@Nullable String name) { - - boolean ignoreCase = SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS; - - // Check whether we have a conflict with an existing or invalid AVD - // known to the manager. - synchronized (mAllAvdList) { - for (AvdInfo info : mAllAvdList) { - String name2 = info.getName(); - if (name2.equals(name) || (ignoreCase && name2.equalsIgnoreCase(name))) { - if (info.getStatus() == AvdStatus.OK) { - return Pair.of(AvdConflict.CONFLICT_EXISTING_AVD, name2); - } else { - return Pair.of(AvdConflict.CONFLICT_INVALID_AVD, name2); - } - } - } - } - - // No conflict with known AVDs. - // Are some existing files/folders in the way of creating this AVD? - - try { - File file = AvdInfo.getDefaultIniFile(this, name); - if (file.exists()) { - return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath()); - } - - file = AvdInfo.getDefaultAvdFolder(this, name, false); - if (file.exists()) { - return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath()); - } - - } catch (AndroidLocationException e) { - // ignore - } - - - return Pair.of(AvdConflict.NO_CONFLICT, null); - } - - /** - * Reloads the AVD list. - * @param log the log object to receive action logs. Cannot be null. - * @throws AndroidLocationException if there was an error finding the location of the - * AVD folder. - */ - public void reloadAvds(@NonNull ILogger log) throws AndroidLocationException { - // build the list in a temp list first, in case the method throws an exception. - // It's better than deleting the whole list before reading the new one. - ArrayList allList = new ArrayList(); - buildAvdList(allList, log); - - synchronized (mAllAvdList) { - mAllAvdList.clear(); - mAllAvdList.addAll(allList); - mValidAvdList = mBrokenAvdList = null; - } - } - - /** - * Creates a new AVD. It is expected that there is no existing AVD with this name already. - * - * @param avdFolder the data folder for the AVD. It will be created as needed. - * Unless you want to locate it in a specific directory, the ideal default is - * {@code AvdManager.AvdInfo.getAvdFolder}. - * @param avdName the name of the AVD - * @param target the target of the AVD - * @param tag the tag of the AVD - * @param abiType the abi type of the AVD - * @param skinFolder the skin folder path to use, if specified. Can be null. - * @param skinName the name of the skin. Can be null. Must have been verified by caller. - * Can be a size in the form "NNNxMMM" or a directory name matching skinFolder. - * @param sdcard the parameter value for the sdCard. Can be null. This is either a path to - * an existing sdcard image or a sdcard size (\d+, \d+K, \dM). - * @param hardwareConfig the hardware setup for the AVD. Can be null to use defaults. - * @param bootProps the optional boot properties for the AVD. Can be null. - * @param createSnapshot If true copy a blank snapshot image into the AVD. - * @param removePrevious If true remove any previous files. - * @param editExisting If true, edit an existing AVD, changing only the minimum required. - * This won't remove files unless required or unless {@code removePrevious} is set. - * @param log the log object to receive action logs. Cannot be null. - * @return The new {@link AvdInfo} in case of success (which has just been added to the - * internal list) or null in case of failure. - */ - @Nullable - public AvdInfo createAvd( - @NonNull File avdFolder, - @NonNull String avdName, - @NonNull IAndroidTarget target, - @NonNull IdDisplay tag, - @NonNull String abiType, - @Nullable File skinFolder, - @Nullable String skinName, - @Nullable String sdcard, - @Nullable Map hardwareConfig, - @Nullable Map bootProps, - boolean createSnapshot, - boolean removePrevious, - boolean editExisting, - @NonNull ILogger log) { - if (log == null) { - throw new IllegalArgumentException("log cannot be null"); - } - - File iniFile = null; - boolean needCleanup = false; - try { - if (avdFolder.exists()) { - if (removePrevious) { - // AVD already exists and removePrevious is set, try to remove the - // directory's content first (but not the directory itself). - try { - deleteContentOf(avdFolder); - } catch (SecurityException e) { - log.error(e, "Failed to delete %1$s", avdFolder.getAbsolutePath()); - } - } else if (!editExisting) { - // AVD shouldn't already exist if removePrevious is false and - // we're not editing an existing AVD. - log.error(null, - "Folder %1$s is in the way. Use --force if you want to overwrite.", - avdFolder.getAbsolutePath()); - return null; - } - } else { - // create the AVD folder. - avdFolder.mkdir(); - // We're not editing an existing AVD. - editExisting = false; - } - - // actually write the ini file - iniFile = createAvdIniFile(avdName, avdFolder, target, removePrevious); - - // writes the userdata.img in it. - - File userdataSrc = null; - - // Look for a system image in the add-on. - // If we don't find one there, look in the base platform. - ISystemImage systemImage = target.getSystemImage(tag, abiType); - - if (systemImage != null) { - File imageFolder = systemImage.getLocation(); - userdataSrc = new File(imageFolder, USERDATA_IMG); - } - - if ((userdataSrc == null || !userdataSrc.exists()) && !target.isPlatform()) { - // If we don't find a system-image in the add-on, look into the platform. - - systemImage = target.getParent().getSystemImage(tag, abiType); - if (systemImage != null) { - File imageFolder = systemImage.getLocation(); - userdataSrc = new File(imageFolder, USERDATA_IMG); - } - } - - if (userdataSrc == null || !userdataSrc.exists()) { - log.error(null, - "Unable to find a '%1$s' file for ABI %2$s to copy into the AVD folder.", - USERDATA_IMG, - abiType); - needCleanup = true; - return null; - } - - File userdataDest = new File(avdFolder, USERDATA_IMG); - - copyImageFile(userdataSrc, userdataDest); - - if (userdataDest.exists() == false) { - log.error(null, "Unable to create '%1$s' file in the AVD folder.", - userdataDest); - needCleanup = true; - return null; - } - - // Config file. - HashMap values = new HashMap(); - - if (setImagePathProperties(target, tag, abiType, values, log) == false) { - log.error(null, "Failed to set image path properties in the AVD folder."); - needCleanup = true; - return null; - } - - // Create the snapshot file - if (createSnapshot) { - File snapshotDest = new File(avdFolder, SNAPSHOTS_IMG); - if (snapshotDest.isFile() && editExisting) { - log.info("Snapshot image already present, was not changed.\n"); - - } else { - File toolsLib = new File(myLocalSdk.getLocation(), - SdkConstants.OS_SDK_TOOLS_LIB_EMULATOR_FOLDER); - File snapshotBlank = new File(toolsLib, SNAPSHOTS_IMG); - if (snapshotBlank.exists() == false) { - log.error(null, - "Unable to find a '%2$s%1$s' file to copy into the AVD folder.", - SNAPSHOTS_IMG, toolsLib); - needCleanup = true; - return null; - } - - copyImageFile(snapshotBlank, snapshotDest); - } - values.put(AVD_INI_SNAPSHOT_PRESENT, "true"); - } - - // Now the tag & abi type - values.put(AVD_INI_TAG_ID, tag.getId()); - values.put(AVD_INI_TAG_DISPLAY, tag.getDisplay()); - values.put(AVD_INI_ABI_TYPE, abiType); - - // and the cpu arch. - Abi abi = Abi.getEnum(abiType); - if (abi != null) { - values.put(AVD_INI_CPU_ARCH, abi.getCpuArch()); - - String model = abi.getCpuModel(); - if (model != null) { - values.put(AVD_INI_CPU_MODEL, model); - } - } else { - log.error(null, - "ABI %1$s is not supported by this version of the SDK Tools", abiType); - needCleanup = true; - return null; - } - - // Now the skin. - String skinPath = null; - - if (skinFolder == null && skinName == null) { - // Nothing specified. Use the default from the target. - skinFolder = target.getDefaultSkin(); - } - - if (skinFolder == null && skinName != null && - NUMERIC_SKIN_SIZE.matcher(skinName).matches()) { - // Numeric skin size. Set both skinPath and skinName to the same size. - skinPath = skinName; - - } else if (skinFolder != null && skinName == null) { - // Skin folder is specified, but not skin name. Adjust it. - skinName = skinFolder.getName(); - - } else if (skinFolder == null && skinName != null) { - // skin folder is not specified, but there's a non-numeric skin name. - // check whether the skin is in the target. - skinFolder = getSkinFolder(skinName, target); - } - - if (skinFolder != null) { - // skin does not exist! - if (!skinFolder.exists()) { - log.error(null, "Skin '%1$s' does not exist.", skinName); - return null; - } - - // if skinFolder is in the sdk, use the relative path - if (skinFolder.getPath().startsWith(myLocalSdk.getLocation().getPath())) { - try { - skinPath = LegacyFileOp.makeRelative(myLocalSdk.getLocation(), skinFolder); - } catch (IOException e) { - // In case it fails, just use the absolute path - skinPath = skinFolder.getAbsolutePath(); - } - } else { - // Skin isn't in the sdk. Just use the absolute path. - skinPath = skinFolder.getAbsolutePath(); - } - } - - // Set skin.name for display purposes in the AVD manager and - // set skin.path for use by the emulator. - if (skinName != null) { - values.put(AVD_INI_SKIN_NAME, skinName); - } - if (skinPath != null) { - values.put(AVD_INI_SKIN_PATH, skinPath); - } - - if (sdcard != null && !sdcard.isEmpty()) { - // Sdcard is possibly a size. In that case we create a file called 'sdcard.img' - // in the AVD folder, and do not put any value in config.ini. - - long sdcardSize = parseSdcardSize(sdcard, null/*parsedStrings*/); - - if (sdcardSize == SDCARD_SIZE_NOT_IN_RANGE) { - log.error(null, "SD Card size must be in the range 9 MiB..1023 GiB."); - needCleanup = true; - return null; - - } else if (sdcardSize == SDCARD_SIZE_INVALID) { - log.error(null, "Unable to parse SD Card size"); - needCleanup = true; - return null; - - } else if (sdcardSize == SDCARD_NOT_SIZE_PATTERN) { - File sdcardFile = new File(sdcard); - if (sdcardFile.isFile()) { - // sdcard value is an external sdcard, so we put its path into the config.ini - values.put(AVD_INI_SDCARD_PATH, sdcard); - } else { - log.error(null, "'%1$s' is not recognized as a valid sdcard value.\n" - + "Value should be:\n" + "1. path to an sdcard.\n" - + "2. size of the sdcard to create: [K|M]", sdcard); - needCleanup = true; - return null; - } - } else { - // create the sdcard. - File sdcardFile = new File(avdFolder, SDCARD_IMG); - - boolean runMkSdcard = true; - if (sdcardFile.exists()) { - if (sdcardFile.length() == sdcardSize && editExisting) { - // There's already an sdcard file with the right size and we're - // not overriding it... so don't remove it. - runMkSdcard = false; - log.info("SD Card already present with same size, was not changed.\n"); - } - } - - if (runMkSdcard) { - String path = sdcardFile.getAbsolutePath(); - - // execute mksdcard with the proper parameters. - File toolsFolder = new File(myLocalSdk.getLocation(), - SdkConstants.FD_TOOLS); - File mkSdCard = new File(toolsFolder, SdkConstants.mkSdCardCmdName()); - - if (mkSdCard.isFile() == false) { - log.error(null, "'%1$s' is missing from the SDK tools folder.", - mkSdCard.getName()); - needCleanup = true; - return null; - } - - if (createSdCard(mkSdCard.getAbsolutePath(), sdcard, path, log) == false) { - log.error(null, "Failed to create sdcard in the AVD folder."); - needCleanup = true; - return null; // mksdcard output has already been displayed, no need to - // output anything else. - } - } - - // add a property containing the size of the sdcard for display purpose - // only when the dev does 'android list avd' - values.put(AVD_INI_SDCARD_SIZE, sdcard); - } - } - - // add the hardware config to the config file. - // priority order is: - // - values provided by the user - // - values provided by the skin - // - values provided by the target (add-on only). - // - values provided by the sys img - // In order to follow this priority, we'll add the lowest priority values first and then - // override by higher priority values. - // In the case of a platform with override values from the user, the skin value might - // already be there, but it's ok. - - HashMap finalHardwareValues = new HashMap(); - - FileWrapper sysImgHardwareFile = new FileWrapper(systemImage.getLocation(), - AvdManager.HARDWARE_INI); - if (sysImgHardwareFile.isFile()) { - Map targetHardwareConfig = ProjectProperties.parsePropertyFile( - sysImgHardwareFile, log); - - if (targetHardwareConfig != null) { - finalHardwareValues.putAll(targetHardwareConfig); - values.putAll(targetHardwareConfig); - } - } - - FileWrapper targetHardwareFile = new FileWrapper(target.getLocation(), - AvdManager.HARDWARE_INI); - if (targetHardwareFile.isFile()) { - Map targetHardwareConfig = ProjectProperties.parsePropertyFile( - targetHardwareFile, log); - - if (targetHardwareConfig != null) { - finalHardwareValues.putAll(targetHardwareConfig); - values.putAll(targetHardwareConfig); - } - } - - // get the hardware properties for this skin - if (skinFolder != null) { - FileWrapper skinHardwareFile = new FileWrapper(skinFolder, AvdManager.HARDWARE_INI); - if (skinHardwareFile.isFile()) { - Map skinHardwareConfig = - ProjectProperties.parsePropertyFile(skinHardwareFile, log); - - if (skinHardwareConfig != null) { - finalHardwareValues.putAll(skinHardwareConfig); - values.putAll(skinHardwareConfig); - } - } - } - - // finally put the hardware provided by the user. - if (hardwareConfig != null) { - finalHardwareValues.putAll(hardwareConfig); - values.putAll(hardwareConfig); - } - - File configIniFile = new File(avdFolder, CONFIG_INI); - writeIniFile(configIniFile, values, true); - - if (bootProps != null && !bootProps.isEmpty()) { - File bootPropsFile = new File(avdFolder, BOOT_PROP); - writeIniFile(bootPropsFile, bootProps, false); - } - - // Generate the log report first because we want to control where line breaks - // are located when generating the hardware config list. - StringBuilder report = new StringBuilder(); - - if (target.isPlatform()) { - if (editExisting) { - report.append(String.format("Updated AVD '%1$s' based on %2$s", - avdName, target.getName())); - } else { - report.append(String.format("Created AVD '%1$s' based on %2$s", - avdName, target.getName())); - } - } else { - if (editExisting) { - report.append(String.format("Updated AVD '%1$s' based on %2$s (%3$s)", avdName, - target.getName(), target.getVendor())); - } else { - report.append(String.format("Created AVD '%1$s' based on %2$s (%3$s)", avdName, - target.getName(), target.getVendor())); - } - } - report.append(String.format(", %s processor", AvdInfo.getPrettyAbiType(tag, abiType))); - - // display the chosen hardware config - if (!finalHardwareValues.isEmpty()) { - report.append(",\nwith the following hardware config:\n"); - List keys = new ArrayList(finalHardwareValues.keySet()); - Collections.sort(keys); - for (String key : keys) { - String value = finalHardwareValues.get(key); - report.append(String.format("%s=%s\n", key, value)); - } - } else { - report.append("\n"); - } - - log.info(report.toString()); - - // create the AvdInfo object, and add it to the list - AvdInfo newAvdInfo = new AvdInfo( - avdName, - iniFile, - avdFolder.getAbsolutePath(), - target.hashString(), - target, - tag, abiType, - values); - - AvdInfo oldAvdInfo = getAvd(avdName, false /*validAvdOnly*/); - - synchronized (mAllAvdList) { - if (oldAvdInfo != null && (removePrevious || editExisting)) { - mAllAvdList.remove(oldAvdInfo); - } - mAllAvdList.add(newAvdInfo); - mValidAvdList = mBrokenAvdList = null; - } - - if ((removePrevious || editExisting) && - newAvdInfo != null && - oldAvdInfo != null && - !oldAvdInfo.getDataFolderPath().equals(newAvdInfo.getDataFolderPath())) { - log.warning("Removing previous AVD directory at %s", - oldAvdInfo.getDataFolderPath()); - // Remove the old data directory - File dir = new File(oldAvdInfo.getDataFolderPath()); - try { - deleteContentOf(dir); - dir.delete(); - } catch (SecurityException e) { - log.error(e, "Failed to delete %1$s", dir.getAbsolutePath()); - } - } - - return newAvdInfo; - } catch (AndroidLocationException e) { - log.error(e, null); - } catch (IOException e) { - log.error(e, null); - } catch (SecurityException e) { - log.error(e, null); - } finally { - if (needCleanup) { - if (iniFile != null && iniFile.exists()) { - iniFile.delete(); - } - - try { - deleteContentOf(avdFolder); - avdFolder.delete(); - } catch (SecurityException e) { - log.error(e, "Failed to delete %1$s", avdFolder.getAbsolutePath()); - } - } - } - - return null; - } - - /** - * Copy the nominated file to the given destination. - * - * @throws FileNotFoundException - * @throws IOException - */ - private void copyImageFile(@NonNull File source, @NonNull File destination) - throws FileNotFoundException, IOException { - FileInputStream fis = new FileInputStream(source); - FileOutputStream fos = new FileOutputStream(destination); - - byte[] buffer = new byte[4096]; - int count; - while ((count = fis.read(buffer)) != -1) { - fos.write(buffer, 0, count); - } - - fos.close(); - fis.close(); - } - - /** - * Returns the path to the target images folder as a relative path to the SDK, if the folder - * is not empty. If the image folder is empty or does not exist, null is returned. - * @throws InvalidTargetPathException if the target image folder is not in the current SDK. - */ - private String getImageRelativePath(@NonNull IAndroidTarget target, - @NonNull IdDisplay tag, - @NonNull String abiType) - throws InvalidTargetPathException { - - ISystemImage systemImage = target.getSystemImage(tag, abiType); - if (systemImage == null) { - // ABI Type is unknown for target - return null; - } - - File folder = systemImage.getLocation(); - String imageFullPath = folder.getAbsolutePath(); - - // make this path relative to the SDK location - String sdkLocation = myLocalSdk.getPath(); - if (!imageFullPath.startsWith(sdkLocation)) { - // this really really should not happen. - assert false; - throw new InvalidTargetPathException("Target location is not inside the SDK."); - } - - if (folder.isDirectory()) { - String[] list = folder.list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return IMAGE_NAME_PATTERN.matcher(name).matches(); - } - }); - - if (list.length > 0) { - // Remove the SDK root path, e.g. /sdk/dir1/dir2 => /dir1/dir2 - imageFullPath = imageFullPath.substring(sdkLocation.length()); - // The path is relative, so it must not start with a file separator - if (imageFullPath.charAt(0) == File.separatorChar) { - imageFullPath = imageFullPath.substring(1); - } - // For compatibility with previous versions, we denote folders - // by ending the path with file separator - if (!imageFullPath.endsWith(File.separator)) { - imageFullPath += File.separator; - } - - return imageFullPath; - } - } - - return null; - } - - /** - * Returns the path to the skin, as a relative path to the SDK. - * @param skinName The name of the skin to find. Case-sensitive. - * @param target The target where to find the skin. - * @param log the log object to receive action logs. Cannot be null. - */ - @Deprecated - private String getSkinRelativePath(@NonNull String skinName, - @NonNull IAndroidTarget target, - @NonNull ILogger log) { - if (log == null) { - throw new IllegalArgumentException("log cannot be null"); - } - - // first look to see if the skin is in the target - File skin = getSkinFolder(skinName, target); - - // skin really does not exist! - if (skin.exists() == false) { - log.error(null, "Skin '%1$s' does not exist.", skinName); - return null; - } - - // get the skin path - String path = skin.getAbsolutePath(); - - // make this path relative to the SDK location - - String sdkLocation = myLocalSdk.getPath(); - if (path.startsWith(sdkLocation) == false) { - // this really really should not happen. - log.error(null, "Target location is not inside the SDK."); - assert false; - return null; - } - - path = path.substring(sdkLocation.length()); - if (path.charAt(0) == File.separatorChar) { - path = path.substring(1); - } - return path; - } - - /** - * Returns the full absolute OS path to a skin specified by name for a given target. - * @param skinName The name of the skin to find. Case-sensitive. - * @param target The target where to find the skin. - * @return a {@link File} that may or may not actually exist. - */ - private File getSkinFolder(@NonNull String skinName, @NonNull IAndroidTarget target) { - String path = target.getPath(IAndroidTarget.SKINS); - File skin = new File(path, skinName); - - if (skin.exists() == false && target.isPlatform() == false) { - target = target.getParent(); - - path = target.getPath(IAndroidTarget.SKINS); - skin = new File(path, skinName); - } - - return skin; - } - - /** - * Creates the ini file for an AVD. - * - * @param name of the AVD. - * @param avdFolder path for the data folder of the AVD. - * @param target of the AVD. - * @param removePrevious True if an existing ini file should be removed. - * @throws AndroidLocationException if there's a problem getting android root directory. - * @throws IOException if {@link File#getAbsolutePath()} fails. - */ - private File createAvdIniFile(@NonNull String name, - @NonNull File avdFolder, - @NonNull IAndroidTarget target, - boolean removePrevious) - throws AndroidLocationException, IOException { - File iniFile = AvdInfo.getDefaultIniFile(this, name); - - if (removePrevious) { - if (iniFile.isFile()) { - iniFile.delete(); - } else if (iniFile.isDirectory()) { - deleteContentOf(iniFile); - iniFile.delete(); - } - } - - String absPath = avdFolder.getAbsolutePath(); - String relPath = null; - String androidPath = AndroidLocation.getFolder(); - if (absPath.startsWith(androidPath)) { - // Compute the AVD path relative to the android path. - assert androidPath.endsWith(File.separator); - relPath = absPath.substring(androidPath.length()); - } - - HashMap values = new HashMap(); - if (relPath != null) { - values.put(AVD_INFO_REL_PATH, relPath); - } - values.put(AVD_INFO_ABS_PATH, absPath); - values.put(AVD_INFO_TARGET, target.hashString()); - writeIniFile(iniFile, values, true); - - return iniFile; - } - - /** - * Creates the ini file for an AVD. - * - * @param info of the AVD. - * @throws AndroidLocationException if there's a problem getting android root directory. - * @throws IOException if {@link File#getAbsolutePath()} fails. - */ - private File createAvdIniFile(@NonNull AvdInfo info) - throws AndroidLocationException, IOException { - return createAvdIniFile(info.getName(), - new File(info.getDataFolderPath()), - info.getTarget(), - false /*removePrevious*/); - } - - /** - * Actually deletes the files of an existing AVD. - *

- * This also remove it from the manager's list, The caller does not need to - * call {@link #removeAvd(AvdInfo)} afterwards. - *

- * This method is designed to somehow work with an unavailable AVD, that is an AVD that - * could not be loaded due to some error. That means this method still tries to remove - * the AVD ini file or its folder if it can be found. An error will be output if any of - * these operations fail. - * - * @param avdInfo the information on the AVD to delete - * @param log the log object to receive action logs. Cannot be null. - * @return True if the AVD was deleted with no error. - */ - public boolean deleteAvd(@NonNull AvdInfo avdInfo, @NonNull ILogger log) { - try { - boolean error = false; - - File f = avdInfo.getIniFile(); - if (f != null && f.exists()) { - log.info("Deleting file %1$s\n", f.getCanonicalPath()); - if (!f.delete()) { - log.error(null, "Failed to delete %1$s\n", f.getCanonicalPath()); - error = true; - } - } - - String path = avdInfo.getDataFolderPath(); - if (path != null) { - f = new File(path); - if (f.exists()) { - log.info("Deleting folder %1$s\n", f.getCanonicalPath()); - if (deleteContentOf(f) == false || f.delete() == false) { - log.error(null, "Failed to delete %1$s\n", f.getCanonicalPath()); - error = true; - } - } - } - - removeAvd(avdInfo); - - if (error) { - log.info("\nAVD '%1$s' deleted with errors. See errors above.\n", - avdInfo.getName()); - } else { - log.info("\nAVD '%1$s' deleted.\n", avdInfo.getName()); - return true; - } - - } catch (IOException e) { - log.error(e, null); - } catch (SecurityException e) { - log.error(e, null); - } - return false; - } - - /** - * Moves and/or rename an existing AVD and its files. - * This also change it in the manager's list. - *

- * The caller should make sure the name or path given are valid, do not exist and are - * actually different than current values. - * - * @param avdInfo the information on the AVD to move. - * @param newName the new name of the AVD if non null. - * @param paramFolderPath the new data folder if non null. - * @param log the log object to receive action logs. Cannot be null. - * @return True if the move succeeded or there was nothing to do. - * If false, this method will have had already output error in the log. - */ - public boolean moveAvd(@NonNull AvdInfo avdInfo, - @Nullable String newName, - @Nullable String paramFolderPath, - @NonNull ILogger log) { - - try { - if (paramFolderPath != null) { - File f = new File(avdInfo.getDataFolderPath()); - log.warning("Moving '%1$s' to '%2$s'.", - avdInfo.getDataFolderPath(), - paramFolderPath); - if (!f.renameTo(new File(paramFolderPath))) { - log.error(null, "Failed to move '%1$s' to '%2$s'.", - avdInfo.getDataFolderPath(), paramFolderPath); - return false; - } - - // update AVD info - AvdInfo info = new AvdInfo( - avdInfo.getName(), - avdInfo.getIniFile(), - paramFolderPath, - avdInfo.getTargetHash(), - avdInfo.getTarget(), - avdInfo.getTag(), - avdInfo.getAbiType(), - avdInfo.getProperties()); - replaceAvd(avdInfo, info); - - // update the ini file - createAvdIniFile(info); - } - - if (newName != null) { - File oldIniFile = avdInfo.getIniFile(); - File newIniFile = AvdInfo.getDefaultIniFile(this, newName); - - log.warning("Moving '%1$s' to '%2$s'.", oldIniFile.getPath(), newIniFile.getPath()); - if (!oldIniFile.renameTo(newIniFile)) { - log.error(null, "Failed to move '%1$s' to '%2$s'.", - oldIniFile.getPath(), newIniFile.getPath()); - return false; - } - - // update AVD info - AvdInfo info = new AvdInfo( - newName, - avdInfo.getIniFile(), - avdInfo.getDataFolderPath(), - avdInfo.getTargetHash(), - avdInfo.getTarget(), - avdInfo.getTag(), - avdInfo.getAbiType(), - avdInfo.getProperties()); - replaceAvd(avdInfo, info); - } - - log.info("AVD '%1$s' moved.\n", avdInfo.getName()); - - } catch (AndroidLocationException e) { - log.error(e, null); - } catch (IOException e) { - log.error(e, null); - } - - // nothing to do or succeeded - return true; - } - - /** - * Helper method to recursively delete a folder's content (but not the folder itself). - * - * @throws SecurityException like {@link File#delete()} does if file/folder is not writable. - */ - private boolean deleteContentOf(File folder) throws SecurityException { - File[] files = folder.listFiles(); - if (files != null) { - for (File f : files) { - if (f.isDirectory()) { - if (deleteContentOf(f) == false) { - return false; - } - } - if (f.delete() == false) { - return false; - } - - } - } - - return true; - } - - /** - * Returns a list of files that are potential AVD ini files. - *

- * This lists the $HOME/.android/avd/.ini files. - * Such files are properties file than then indicate where the AVD folder is located. - *

- * Note: the method is to be considered private. It is made protected so that - * unit tests can easily override the AVD root. - * - * @return A new {@link File} array or null. The array might be empty. - * @throws AndroidLocationException if there's a problem getting android root directory. - */ - private File[] buildAvdFilesList() throws AndroidLocationException { - File folder = new File(getBaseAvdFolder()); - - // ensure folder validity. - if (folder.isFile()) { - throw new AndroidLocationException( - String.format("%1$s is not a valid folder.", folder.getAbsolutePath())); - } else if (folder.exists() == false) { - // folder is not there, we create it and return - folder.mkdirs(); - return null; - } - - File[] avds = folder.listFiles(new FilenameFilter() { - @Override - public boolean accept(File parent, String name) { - if (INI_NAME_PATTERN.matcher(name).matches()) { - // check it's a file and not a folder - boolean isFile = new File(parent, name).isFile(); - return isFile; - } - - return false; - } - }); - - return avds; - } - - /** - * Computes the internal list of available AVDs - * @param allList the list to contain all the AVDs - * @param log the log object to receive action logs. Cannot be null. - * - * @throws AndroidLocationException if there's a problem getting android root directory. - */ - private void buildAvdList(ArrayList allList, ILogger log) - throws AndroidLocationException { - File[] avds = buildAvdFilesList(); - if (avds != null) { - for (File avd : avds) { - AvdInfo info = parseAvdInfo(avd, log); - if (info != null && !allList.contains(info)) { - allList.add(info); - } - } - } - } - - private DeviceManager getDeviceManager(ILogger logger) { - DeviceManager manager = myDeviceManagers.get(logger); - if (manager == null) { - manager = DeviceManager.createInstance(myLocalSdk.getLocation(), logger); - manager.registerListener(new DeviceManager.DevicesChangedListener() { - @Override - public void onDevicesChanged() { - myDeviceManagers.clear(); - } - }); - myDeviceManagers.put(logger, manager); - } - return manager; - } - - /** - * Parses an AVD .ini file to create an {@link AvdInfo}. - * - * @param iniPath The path to the AVD .ini file - * @param log the log object to receive action logs. Cannot be null. - * @return A new {@link AvdInfo} with an {@link AvdStatus} indicating whether this AVD is - * valid or not. - */ - private AvdInfo parseAvdInfo(File iniPath, ILogger log) { - Map map = parseIniFile( - new FileWrapper(iniPath), - log); - - String avdPath = map.get(AVD_INFO_ABS_PATH); - String targetHash = map.get(AVD_INFO_TARGET); - - if (!(new File(avdPath).isDirectory())) { - // Try to fallback on the relative path, if present. - String relPath = map.get(AVD_INFO_REL_PATH); - if (relPath != null) { - try { - String androidPath = AndroidLocation.getFolder(); - File f = new File(androidPath, relPath); - if (f.isDirectory()) { - avdPath = f.getAbsolutePath(); - } - } catch (AndroidLocationException ignore) {} - } - } - - IAndroidTarget target = null; - FileWrapper configIniFile = null; - Map properties = null; - - if (targetHash != null) { - target = myLocalSdk.getTargetFromHashString(targetHash); - } - - // load the AVD properties. - if (avdPath != null) { - configIniFile = new FileWrapper(avdPath, CONFIG_INI); - } - - if (configIniFile != null) { - if (!configIniFile.isFile()) { - log.warning("Missing file '%1$s'.", configIniFile.getPath()); - } else { - properties = parseIniFile(configIniFile, log); - } - } - - // get name - String name = iniPath.getName(); - Matcher matcher = INI_NAME_PATTERN.matcher(iniPath.getName()); - if (matcher.matches()) { - name = matcher.group(1); - } - - // get tag - IdDisplay tag = SystemImage.DEFAULT_TAG; - String tagId = properties == null ? null : properties.get(AVD_INI_TAG_ID); - if (tagId != null) { - String tagDisp = properties == null ? null : properties.get(AVD_INI_TAG_DISPLAY); - if (tagDisp == null || tagDisp.isEmpty()) { - tagDisp = LocalSysImgPkgInfo.tagIdToDisplay(tagId); - } - tag = new IdDisplay(tagId, tagDisp); - } - - // get abi type - String abiType = properties == null ? null : properties.get(AVD_INI_ABI_TYPE); - // for the avds created previously without enhancement, i.e. They are created based - // on previous API Levels. They are supposed to have ARM processor type - if (abiType == null) { - abiType = SdkConstants.ABI_ARMEABI; - } - - // check the image.sysdir are valid - boolean validImageSysdir = true; - if (properties != null) { - String imageSysDir = properties.get(AVD_INI_IMAGES_1); - if (imageSysDir != null) { - File f = new File(myLocalSdk.getLocation(), imageSysDir); - if (f.isDirectory() == false) { - validImageSysdir = false; - } else { - imageSysDir = properties.get(AVD_INI_IMAGES_2); - if (imageSysDir != null) { - f = new File(myLocalSdk.getLocation(), imageSysDir); - if (f.isDirectory() == false) { - validImageSysdir = false; - } - } - } - } - } - - // Check the system image from the target - ISystemImage sysImage = target != null ? target.getSystemImage(tag, abiType) : null; - - // Get the device status if this AVD is associated with a device - DeviceStatus deviceStatus = null; - boolean updateHashV2 = false; - if (properties != null) { - String deviceName = properties.get(AVD_INI_DEVICE_NAME); - String deviceMfctr = properties.get(AVD_INI_DEVICE_MANUFACTURER); - - Device d = null; - - if (deviceName != null && deviceMfctr != null) { - DeviceManager devMan = getDeviceManager(log); - d = devMan.getDevice(deviceName, deviceMfctr); - deviceStatus = d == null ? DeviceStatus.MISSING : DeviceStatus.EXISTS; - - if (d != null) { - updateHashV2 = true; - String hashV2 = properties.get(AVD_INI_DEVICE_HASH_V2); - if (hashV2 != null) { - String newHashV2 = DeviceManager.hasHardwarePropHashChanged(d, hashV2); - if (newHashV2 == null) { - updateHashV2 = false; - } else { - properties.put(AVD_INI_DEVICE_HASH_V2, newHashV2); - } - } - - String hashV1 = properties.get(AVD_INI_DEVICE_HASH_V1); - if (hashV1 != null) { - // will recompute a hash v2 and save it below - properties.remove(AVD_INI_DEVICE_HASH_V1); - } - } - } - } - - - // TODO: What about missing sdcard, skins, etc? - - AvdStatus status; - - if (avdPath == null) { - status = AvdStatus.ERROR_PATH; - } else if (configIniFile == null) { - status = AvdStatus.ERROR_CONFIG; - } else if (targetHash == null) { - status = AvdStatus.ERROR_TARGET_HASH; - } else if (target == null) { - status = AvdStatus.ERROR_TARGET; - } else if (properties == null) { - status = AvdStatus.ERROR_PROPERTIES; - } else if (validImageSysdir == false) { - status = AvdStatus.ERROR_IMAGE_DIR; - } else if (deviceStatus == DeviceStatus.CHANGED) { - status = AvdStatus.ERROR_DEVICE_CHANGED; - } else if (deviceStatus == DeviceStatus.MISSING) { - status = AvdStatus.ERROR_DEVICE_MISSING; - } else if (sysImage == null) { - status = AvdStatus.ERROR_IMAGE_MISSING; - } else { - status = AvdStatus.OK; - } - - AvdInfo info = new AvdInfo( - name, - iniPath, - avdPath, - targetHash, - target, - tag, - abiType, - properties, - status); - - if (updateHashV2) { - try { - return updateDeviceChanged(info, log); - } catch (IOException ignore) {} - } - - return info; - } - - /** - * Writes a .ini file from a set of properties, using UTF-8 encoding. - * The keys are sorted. - * The file should be read back later by {@link #parseIniFile(IAbstractFile, ILogger)}. - * - * @param iniFile The file to generate. - * @param values The properties to place in the ini file. - * @param addEncoding When true, add a property {@link #AVD_INI_ENCODING} indicating the - * encoding used to write the file. - * @throws IOException if {@link FileWriter} fails to open, write or close the file. - */ - private static void writeIniFile(File iniFile, Map values, boolean addEncoding) - throws IOException { - - Charset charset = Charsets.UTF_8; - OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(iniFile), charset); - try { - if (addEncoding) { - // Write down the charset used in case we want to use it later. - writer.write(String.format("%1$s=%2$s\n", AVD_INI_ENCODING, charset.name())); - } - - ArrayList keys = new ArrayList(values.keySet()); - Collections.sort(keys); - - for (String key : keys) { - String value = values.get(key); - writer.write(String.format("%1$s=%2$s\n", key, value)); - } - } finally { - writer.close(); - } - } - - /** - * Parses a property file and returns a map of the content. - *

- * If the file is not present, null is returned with no error messages sent to the log. - *

- * Charset encoding will be either the system's default or the one specified by the - * {@link #AVD_INI_ENCODING} key if present. - * - * @param propFile the property file to parse - * @param log the ILogger object receiving warning/error from the parsing. - * @return the map of (key,value) pairs, or null if the parsing failed. - */ - private static Map parseIniFile( - @NonNull IAbstractFile propFile, - @Nullable ILogger log) { - return parseIniFileImpl(propFile, log, null /*charset*/); - } - - /** - * Implementation helper for the {@link #parseIniFile(IAbstractFile, ILogger)} method. - * Don't call this one directly. - * - * @param propFile the property file to parse - * @param log the ILogger object receiving warning/error from the parsing. - * @param charset When a specific charset is specified, this will be used as-is. - * When null, the default charset will first be used and if the key - * {@link #AVD_INI_ENCODING} is found the parsing will restart using that specific - * charset. - * @return the map of (key,value) pairs, or null if the parsing failed. - */ - private static Map parseIniFileImpl( - @NonNull IAbstractFile propFile, - @Nullable ILogger log, - @Nullable Charset charset) { - - BufferedReader reader = null; - try { - boolean canChangeCharset = false; - if (charset == null) { - canChangeCharset = true; - charset = Charsets.ISO_8859_1; - } - reader = new BufferedReader(new InputStreamReader(propFile.getContents(), charset)); - - String line = null; - Map map = new HashMap(); - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (!line.isEmpty() && line.charAt(0) != '#') { - - Matcher m = INI_LINE_PATTERN.matcher(line); - if (m.matches()) { - // Note: we do NOT escape values. - String key = m.group(1); - String value = m.group(2); - - // If we find the charset encoding and it's not the same one and - // it's a valid one, re-read the file using that charset. - if (canChangeCharset && - AVD_INI_ENCODING.equals(key) && - !charset.name().equals(value) && - Charset.isSupported(value)) { - charset = Charset.forName(value); - return parseIniFileImpl(propFile, log, charset); - } - - map.put(key, value); - } else { - if (log != null) { - log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax", - propFile.getOsLocation(), - 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.", - propFile.getOsLocation(), - e.getMessage()); - } - } catch (StreamException e) { - if (log != null) { - log.warning("Error parsing '%1$s': %2$s.", - propFile.getOsLocation(), - e.getMessage()); - } - } finally { - try { - Closeables.close(reader, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen. - } - } - - return null; - } - - /** - * Invokes the tool to create a new SD card image file. - * - * @param toolLocation The path to the mksdcard tool. - * @param size The size of the new SD Card, compatible with {@link #SDCARD_SIZE_PATTERN}. - * @param location The path of the new sdcard image file to generate. - * @param log the log object to receive action logs. Cannot be null. - * @return True if the sdcard could be created. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected boolean createSdCard(String toolLocation, String size, String location, ILogger log) { - try { - String[] command = new String[3]; - command[0] = toolLocation; - command[1] = size; - command[2] = location; - Process process = Runtime.getRuntime().exec(command); - - final ArrayList errorOutput = new ArrayList(); - final ArrayList stdOutput = new ArrayList(); - - int status = GrabProcessOutput.grabProcessOutput( - process, - Wait.WAIT_FOR_READERS, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - if (line != null) { - stdOutput.add(line); - } - } - - @Override - public void err(@Nullable String line) { - if (line != null) { - errorOutput.add(line); - } - } - }); - - if (status == 0) { - return true; - } else { - for (String error : errorOutput) { - log.error(null, error); - } - } - - } catch (InterruptedException e) { - // pass, print error below - } catch (IOException e) { - // pass, print error below - } - - log.error(null, "Failed to create the SD card."); - return false; - } - - /** - * Removes an {@link AvdInfo} from the internal list. - * - * @param avdInfo The {@link AvdInfo} to remove. - * @return true if this {@link AvdInfo} was present and has been removed. - */ - public boolean removeAvd(AvdInfo avdInfo) { - synchronized (mAllAvdList) { - if (mAllAvdList.remove(avdInfo)) { - mValidAvdList = mBrokenAvdList = null; - return true; - } - } - - return false; - } - - /** - * Updates an AVD with new path to the system image folders. - * @param name the name of the AVD to update. - * @param log the log object to receive action logs. Cannot be null. - * @throws IOException - */ - public void updateAvd(String name, ILogger log) throws IOException { - // find the AVD to update. It should be be in the broken list. - AvdInfo avd = null; - synchronized (mAllAvdList) { - for (AvdInfo info : mAllAvdList) { - if (info.getName().equals(name)) { - avd = info; - break; - } - } - } - - if (avd == null) { - // not in the broken list, just return. - log.error(null, "There is no Android Virtual Device named '%s'.", name); - return; - } - - updateAvd(avd, log); - } - - - /** - * Updates an AVD with new path to the system image folders. - * @param avd the AVD to update. - * @param log the log object to receive action logs. Cannot be null. - * @throws IOException - */ - public AvdInfo updateAvd(AvdInfo avd, ILogger log) throws IOException { - // get the properties. This is a unmodifiable Map. - Map oldProperties = avd.getProperties(); - - // create a new map - Map properties = new HashMap(); - if (oldProperties != null) { - properties.putAll(oldProperties); - } - - AvdStatus status; - - // create the path to the new system images. - if (setImagePathProperties(avd.getTarget(), - avd.getTag(), - avd.getAbiType(), - properties, - log)) { - if (properties.containsKey(AVD_INI_IMAGES_1)) { - log.info("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_1, - properties.get(AVD_INI_IMAGES_1)); - } - - if (properties.containsKey(AVD_INI_IMAGES_2)) { - log.info("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_2, - properties.get(AVD_INI_IMAGES_2)); - } - - status = AvdStatus.OK; - } else { - log.error(null, "Unable to find non empty system images folders for %1$s", - avd.getName()); - //FIXME: display paths to empty image folders? - status = AvdStatus.ERROR_IMAGE_DIR; - } - - return updateAvd(avd, properties, status, log); - } - - public AvdInfo updateAvd(AvdInfo avd, - Map newProperties, - AvdStatus status, - ILogger log) throws IOException { - // now write the config file - File configIniFile = new File(avd.getDataFolderPath(), CONFIG_INI); - writeIniFile(configIniFile, newProperties, true); - - // finally create a new AvdInfo for this unbroken avd and add it to the list. - // instead of creating the AvdInfo object directly we reparse it, to detect other possible - // errors - // FIXME: We may want to create this AvdInfo by reparsing the AVD instead. This could detect other errors. - AvdInfo newAvd = new AvdInfo( - avd.getName(), - avd.getIniFile(), - avd.getDataFolderPath(), - avd.getTargetHash(), - avd.getTarget(), - avd.getTag(), - avd.getAbiType(), - newProperties); - - replaceAvd(avd, newAvd); - - return newAvd; - } - - /** - * Updates the device-specific part of an AVD ini. - * @param avd the AVD to update. - * @param log the log object to receive action logs. Cannot be null. - * @return The new AVD on success. - * @throws IOException - */ - public AvdInfo updateDeviceChanged(AvdInfo avd, ILogger log) throws IOException { - - // Overwrite the properties derived from the device and nothing else - Map properties = new HashMap(avd.getProperties()); - - DeviceManager devMan = getDeviceManager(log); - Collection devices = devMan.getDevices(DeviceManager.ALL_DEVICES); - String name = properties.get(AvdManager.AVD_INI_DEVICE_NAME); - String manufacturer = properties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); - - if (properties != null && devices != null && name != null && manufacturer != null) { - for (Device d : devices) { - if (d.getId().equals(name) && d.getManufacturer().equals(manufacturer)) { - properties.putAll(DeviceManager.getHardwareProperties(d)); - try { - return updateAvd(avd, properties, AvdStatus.OK, log); - } catch (IOException e) { - log.error(e, null); - } - } - } - } else { - log.error(null, "Base device information incomplete or missing."); - } - return null; - } - - /** - * Sets the paths to the system images in a properties map. - * - * @param target the target in which to find the system images. - * @param abiType the abi type of the avd to find - * the architecture-dependent system images. - * @param properties the properties in which to set the paths. - * @param log the log object to receive action logs. Cannot be null. - * @return true if success, false if some path are missing. - */ - private boolean setImagePathProperties(IAndroidTarget target, - IdDisplay tag, - String abiType, - Map properties, - ILogger log) { - properties.remove(AVD_INI_IMAGES_1); - properties.remove(AVD_INI_IMAGES_2); - - try { - String property = AVD_INI_IMAGES_1; - - // First the image folders of the target itself - String imagePath = getImageRelativePath(target, tag, abiType); - if (imagePath != null) { - properties.put(property, imagePath); - property = AVD_INI_IMAGES_2; - } - - // If the target is an add-on we need to add the Platform image as a backup. - IAndroidTarget parent = target.getParent(); - if (parent != null) { - imagePath = getImageRelativePath(parent, tag, abiType); - if (imagePath != null) { - properties.put(property, imagePath); - } - } - - // we need at least one path! - return properties.containsKey(AVD_INI_IMAGES_1); - } catch (InvalidTargetPathException e) { - log.error(e, e.getMessage()); - } - - return false; - } - - /** - * Replaces an old {@link AvdInfo} with a new one in the lists storing them. - * @param oldAvd the {@link AvdInfo} to remove. - * @param newAvd the {@link AvdInfo} to add. - */ - private void replaceAvd(AvdInfo oldAvd, AvdInfo newAvd) { - synchronized (mAllAvdList) { - mAllAvdList.remove(oldAvd); - mAllAvdList.add(newAvd); - mValidAvdList = mBrokenAvdList = null; - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/HardwareProperties.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/HardwareProperties.java deleted file mode 100644 index 6b91b459..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/avd/HardwareProperties.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * 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.internal.avd; - -import com.android.utils.ILogger; -import com.google.common.base.Charsets; - -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.Map; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class HardwareProperties { - /** AVD/config.ini key for whether hardware buttons are present. */ - public static final String HW_MAINKEYS = "hw.mainKeys"; - - /** AVD/config.ini key indicating whether trackball is present. */ - public static final String HW_TRACKBALL = "hw.trackBall"; - - /** AVD/config.ini key indicating whether qwerty keyboard is present. */ - public static final String HW_KEYBOARD = "hw.keyboard"; - - /** AVD/config.ini key indicating whether dpad is present. */ - public static final String HW_DPAD = "hw.dPad"; - - /** AVD/config.ini key indicating whether gps is present. */ - public static final String HW_GPS = "hw.gps"; - - /** AVD/config.ini key indicating whether the device is running on battery. */ - public static final String HW_BATTERY = "hw.battery"; - - /** AVD/config.ini key indicating whether accelerometer is present. */ - public static final String HW_ACCELEROMETER = "hw.accelerometer"; - - /** AVD/config.ini key indicating whether gyroscope is present. */ - public static final String HW_ORIENTATION_SENSOR = "hw.sensors.orientation"; - - /** AVD/config.ini key indicating whether h/w mic is present. */ - public static final String HW_AUDIO_INPUT = "hw.audioInput"; - - /** AVD/config.ini key indicating whether sdcard is present. */ - public static final String HW_SDCARD = "hw.sdCard"; - - /** AVD/config.ini key for LCD density. */ - public static final String HW_LCD_DENSITY = "hw.lcd.density"; - - /** AVD/config.ini key indicating whether proximity sensor present. */ - public static final String HW_PROXIMITY_SENSOR = "hw.sensors.proximity"; - - /** AVD/config.ini key for initial device orientation. */ - public static final String HW_INITIAL_ORIENTATION = "hw.initialOrientation"; - - - private static final Pattern PATTERN_PROP = Pattern.compile( - "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); - - /** Property name in the generated avd config file; String; e.g. "hw.screen" */ - private static final String HW_PROP_NAME = "name"; //$NON-NLS-1$ - /** Property type, one of {@link HardwarePropertyType} */ - private static final String HW_PROP_TYPE = "type"; //$NON-NLS-1$ - /** Default value of the property. String matching the property type. */ - private static final String HW_PROP_DEFAULT = "default"; //$NON-NLS-1$ - /** User-visible name of the property. String. */ - private static final String HW_PROP_ABSTRACT = "abstract"; //$NON-NLS-1$ - /** User-visible description of the property. String. */ - private static final String HW_PROP_DESC = "description"; //$NON-NLS-1$ - /** Comma-separate values for a property of type "enum" */ - private static final String HW_PROP_ENUM = "enum"; //$NON-NLS-1$ - - public static final String BOOLEAN_YES = "yes"; - public static final String BOOLEAN_NO = "no"; - public static final Pattern DISKSIZE_PATTERN = Pattern.compile("\\d+[MK]B"); //$NON-NLS-1$ - - /** Represents the type of a hardware property value. */ - public enum HardwarePropertyType { - INTEGER ("integer", false /*isEnum*/), //$NON-NLS-1$ - BOOLEAN ("boolean", false /*isEnum*/), //$NON-NLS-1$ - DISKSIZE ("diskSize", false /*isEnum*/), //$NON-NLS-1$ - STRING ("string", false /*isEnum*/), //$NON-NLS-1$ - INTEGER_ENUM("integer", true /*isEnum*/), //$NON-NLS-1$ - STRING_ENUM ("string", true /*isEnum*/); //$NON-NLS-1$ - - - private String mName; - private boolean mIsEnum; - - HardwarePropertyType(String name, boolean isEnum) { - mName = name; - mIsEnum = isEnum; - } - - /** Returns the name of the type (e.g. "string", "boolean", etc.) */ - public String getName() { - return mName; - } - - /** Indicates whether this type is an enum (e.g. "enum of strings"). */ - public boolean isEnum() { - return mIsEnum; - } - - /** Returns the internal HardwarePropertyType object matching the given type name. */ - public static HardwarePropertyType getEnum(String name, boolean isEnum) { - for (HardwarePropertyType type : values()) { - if (type.mName.equals(name) && type.mIsEnum == isEnum) { - return type; - } - } - - return null; - } - } - - public static final class HardwareProperty { - private String mName; - private HardwarePropertyType mType; - /** the string representation of the default value. can be null. */ - private String mDefault; - /** the choices for an enum. Null if not an enum. */ - private String[] mEnum; - private String mAbstract; - private String mDescription; - - public HardwareProperty() { - // initialize strings to sane defaults, as not all properties will be set from - // the ini file - mName = ""; - mDefault = ""; - mAbstract = ""; - mDescription = ""; - } - - /** Returns the hardware config name of the property, e.g. "hw.screen" */ - public String getName() { - return mName; - } - - /** Returns the property type, one of {@link HardwarePropertyType} */ - public HardwarePropertyType getType() { - return mType; - } - - /** - * Returns the default value of the property. - * String matching the property type. - * Can be null. - */ - public String getDefault() { - return mDefault; - } - - /** Returns the user-visible name of the property. */ - public String getAbstract() { - return mAbstract; - } - - /** Returns the user-visible description of the property. */ - public String getDescription() { - return mDescription; - } - - /** Returns the possible values for an enum property. Can be null. */ - public String[] getEnum() { - return mEnum; - } - - public boolean isValidForUi() { - // don't display single string type for now. - return mType != HardwarePropertyType.STRING || mType.isEnum(); - } - } - - /** - * Parses the hardware definition file. - * @param file the property file to parse - * @param log the ILogger object receiving warning/error from the parsing. Cannot be null. - * @return the map of (key,value) pairs, or null if the parsing failed. - */ - public static Map parseHardwareDefinitions(File file, ILogger log) { - BufferedReader reader = null; - try { - FileInputStream fis = new FileInputStream(file); - reader = new BufferedReader(new InputStreamReader(fis, Charsets.UTF_8)); - - Map map = new TreeMap(); - - String line = null; - HardwareProperty prop = null; - while ((line = reader.readLine()) != null) { - if (!line.isEmpty() && line.charAt(0) != '#') { - Matcher m = PATTERN_PROP.matcher(line); - if (m.matches()) { - String key = m.group(1); - String value = m.group(2); - - if (HW_PROP_NAME.equals(key)) { - prop = new HardwareProperty(); - prop.mName = value; - map.put(prop.mName, 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(key)) { - // Note: we don't know yet whether this type is an enum. - // This is indicated by the "enum = value" line that is parsed later. - prop.mType = HardwarePropertyType.getEnum(value, false); - assert (prop.mType != null); - } else if (HW_PROP_DEFAULT.equals(key)) { - prop.mDefault = value; - } else if (HW_PROP_ABSTRACT.equals(key)) { - prop.mAbstract = value; - } else if (HW_PROP_DESC.equals(key)) { - prop.mDescription = value; - } else if (HW_PROP_ENUM.equals(key)) { - if (!prop.mType.isEnum()) { - // Change the type to an enum, if valid. - prop.mType = HardwarePropertyType.getEnum(prop.mType.getName(), - true); - assert (prop.mType != null); - } - - // Sanitize input: trim spaces, ignore empty entries. - String[] v = value.split(","); - int n = 0; - for (int i = 0; i < v.length; i++) { - String s = v[i] = v[i].trim(); - if (!s.isEmpty()) { - n++; - } - } - prop.mEnum = new String[n]; - n = 0; - for (int i = 0; i < v.length; i++) { - String s = v[i]; - if (!s.isEmpty()) { - prop.mEnum[n++] = s; - } - } - } - } 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) { - log.warning("Error parsing '%1$s': %2$s.", file.getAbsolutePath(), - e.getMessage()); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // ignore - } - } - } - - return null; - } - - /** - * Returns the boolean value matching the given index. - * This is the reverse of {@link #getBooleanValueIndex(String)}. - * - * @param index 0 or 1. - * @return {@link #BOOLEAN_YES} for 0 or {@link #BOOLEAN_NO} for 1. - * @throws IndexOutOfBoundsException if index is neither 0 nor 1. - */ - public static String getBooleanValue(int index) { - if (index == 0) { - return BOOLEAN_YES; - } else if (index == 1) { - return BOOLEAN_NO; - } - throw new IndexOutOfBoundsException("HardwareProperty boolean index must 0 (true) or 1 (false) but was " + index); - } - - /** - * Returns the index of a boolean value. - * This if the reverse of {@link #getBooleanValue(int)}. - * - * @param value Either {@link #BOOLEAN_YES} or {@link #BOOLEAN_NO}. - * @return 0 for {@link #BOOLEAN_YES}, 1 for {@link #BOOLEAN_NO} or -1 for anything else. - */ - public static int getBooleanValueIndex(String value) { - if (BOOLEAN_YES.equals(value)) { - return 0; - } else if (BOOLEAN_NO.equals(value)) { - return 1; - } - - return -1; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfig.template b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfig.template deleted file mode 100644 index 0344b55c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfig.template +++ /dev/null @@ -1,6 +0,0 @@ -/** Automatically generated file. DO NOT MODIFY */ -package #PACKAGE#; - -public final class BuildConfig { - public final static boolean DEBUG = #DEBUG#; -} \ No newline at end of file diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfigGenerator.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfigGenerator.java deleted file mode 100644 index 96fa976d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/BuildConfigGenerator.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.build; - -import com.android.SdkConstants; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Class able to generate a BuildConfig class in Android project. - * The BuildConfig class contains constants related to the build target. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public class BuildConfigGenerator { - - public static final String BUILD_CONFIG_NAME = "BuildConfig.java"; - - private static final String PH_PACKAGE = "#PACKAGE#"; - private static final String PH_DEBUG = "#DEBUG#"; - - private final String mGenFolder; - private final String mAppPackage; - private final boolean mDebug; - - /** - * Creates a generator - * @param genFolder the gen folder of the project - * @param appPackage the application package - * @param debug whether it's a debug build - */ - public BuildConfigGenerator(String genFolder, String appPackage, boolean debug) { - mGenFolder = genFolder; - mAppPackage = appPackage; - mDebug = debug; - } - - /** - * Returns a File representing where the BuildConfig class will be. - */ - public File getFolderPath() { - File genFolder = new File(mGenFolder); - return new File(genFolder, mAppPackage.replace('.', File.separatorChar)); - } - - public File getBuildConfigFile() { - File folder = getFolderPath(); - return new File(folder, BUILD_CONFIG_NAME); - } - - /** - * Generates the BuildConfig class. - */ - public void generate() throws IOException { - String template = readEmbeddedTextFile("BuildConfig.template"); - - Map map = new HashMap(); - map.put(PH_PACKAGE, mAppPackage); - map.put(PH_DEBUG, Boolean.toString(mDebug)); - - String content = replaceParameters(template, map); - - File pkgFolder = getFolderPath(); - if (pkgFolder.isDirectory() == false) { - pkgFolder.mkdirs(); - } - - File buildConfigJava = new File(pkgFolder, BUILD_CONFIG_NAME); - writeFile(buildConfigJava, content); - } - - /** - * Reads and returns the content of a text file embedded in the jar file. - * @param filepath the file path to the text file - * @return null if the file could not be read - * @throws IOException - */ - private String readEmbeddedTextFile(String filepath) throws IOException { - InputStream is = BuildConfigGenerator.class.getResourceAsStream(filepath); - if (is != null) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - - String line; - StringBuilder total = new StringBuilder(reader.readLine()); - while ((line = reader.readLine()) != null) { - total.append('\n'); - total.append(line); - } - - return total.toString(); - } - - // this really shouldn't happen unless the sdklib packaging is broken. - throw new IOException("BuildConfig template is missing!"); - } - - private void writeFile(File file, String content) throws IOException { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - InputStream source = new ByteArrayInputStream(content.getBytes(SdkConstants.UTF_8)); - - byte[] buffer = new byte[1024]; - int count = 0; - while ((count = source.read(buffer)) != -1) { - fos.write(buffer, 0, count); - } - } finally { - if (fos != null) { - fos.close(); - } - } - } - - /** - * Replaces placeholders found in a string with values. - * - * @param str the string to search for placeholders. - * @param parameters a map of to search for in the string - * @return A new String object with the placeholder replaced by the values. - */ - private String replaceParameters(String str, Map parameters) { - - for (Entry entry : parameters.entrySet()) { - String value = entry.getValue(); - if (value != null) { - str = str.replaceAll(entry.getKey(), value); - } - } - - return str; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/DebugKeyProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/DebugKeyProvider.java deleted file mode 100644 index 0f492eab..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/DebugKeyProvider.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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.internal.build; - -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.UnrecoverableEntryException; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; - -/** - * A provider of a dummy key to sign Android application for debugging purpose. - *

This provider uses a custom keystore to create and store a key with a known password. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public class DebugKeyProvider { - - public interface IKeyGenOutput { - void out(String message); - void err(String message); - } - - private static final String PASSWORD_STRING = "android"; - private static final char[] PASSWORD_CHAR = PASSWORD_STRING.toCharArray(); - private static final String DEBUG_ALIAS = "AndroidDebugKey"; - - // Certificate CN value. This is a hard-coded value for the debug key. - // Android Market checks against this value in order to refuse applications signed with - // debug keys. - private static final String CERTIFICATE_DESC = "CN=Android Debug,O=Android,C=US"; - - private KeyStore.PrivateKeyEntry mEntry; - - public static class KeytoolException extends Exception { - /** default serial uid */ - private static final long serialVersionUID = 1L; - private String mJavaHome = null; - private String mCommandLine = null; - - KeytoolException(String message) { - super(message); - } - - KeytoolException(String message, String javaHome, String commandLine) { - super(message); - - mJavaHome = javaHome; - mCommandLine = commandLine; - } - - public String getJavaHome() { - return mJavaHome; - } - - public String getCommandLine() { - return mCommandLine; - } - } - - /** - * Creates a provider using a keystore at the given location. - *

The keystore, and a new random android debug key are created if they do not yet exist. - *

Password for the store/key is android, and the key alias is - * AndroidDebugKey. - * @param osKeyStorePath the OS path to the keystore, or null if the default one - * is to be used. - * @param storeType an optional keystore type, or null if the default is to - * be used. - * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr - * of the keytool process call. - * @throws KeytoolException If the creation of the debug key failed. - * @throws AndroidLocationException - */ - public DebugKeyProvider(String osKeyStorePath, String storeType, IKeyGenOutput output) - throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - UnrecoverableEntryException, IOException, KeytoolException, AndroidLocationException { - - if (osKeyStorePath == null) { - osKeyStorePath = getDefaultKeyStoreOsPath(); - } - - if (loadKeyEntry(osKeyStorePath, storeType) == false) { - // create the store with the key - createNewStore(osKeyStorePath, storeType, output); - } - } - - /** - * Returns the OS path to the default debug keystore. - * - * @return The OS path to the default debug keystore. - * @throws KeytoolException - * @throws AndroidLocationException - */ - public static String getDefaultKeyStoreOsPath() - throws KeytoolException, AndroidLocationException { - String folder = AndroidLocation.getFolder(); - if (folder == null) { - throw new KeytoolException("Failed to get HOME directory!\n"); - } - String osKeyStorePath = folder + "debug.keystore"; - - return osKeyStorePath; - } - - /** - * Returns the debug {@link PrivateKey} to use to sign applications for debug purpose. - * @return the private key or null if its creation failed. - */ - @SuppressWarnings("unused") // the thrown Exceptions are not actually thrown - public PrivateKey getDebugKey() throws KeyStoreException, NoSuchAlgorithmException, - UnrecoverableKeyException, UnrecoverableEntryException { - if (mEntry != null) { - return mEntry.getPrivateKey(); - } - - return null; - } - - /** - * Returns the debug {@link Certificate} to use to sign applications for debug purpose. - * @return the certificate or null if its creation failed. - */ - @SuppressWarnings("unused") // the thrown Exceptions are not actually thrown - public Certificate getCertificate() throws KeyStoreException, NoSuchAlgorithmException, - UnrecoverableKeyException, UnrecoverableEntryException { - if (mEntry != null) { - return mEntry.getCertificate(); - } - - return null; - } - - /** - * Loads the debug key from the keystore. - * @param osKeyStorePath the OS path to the keystore. - * @param storeType an optional keystore type, or null if the default is to - * be used. - * @return true if success, false if the keystore does not exist. - */ - private boolean loadKeyEntry(String osKeyStorePath, String storeType) throws KeyStoreException, - NoSuchAlgorithmException, CertificateException, IOException, - UnrecoverableEntryException { - FileInputStream fis = null; - try { - KeyStore keyStore = KeyStore.getInstance( - storeType != null ? storeType : KeyStore.getDefaultType()); - fis = new FileInputStream(osKeyStorePath); - keyStore.load(fis, PASSWORD_CHAR); - mEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry( - DEBUG_ALIAS, new KeyStore.PasswordProtection(PASSWORD_CHAR)); - } catch (FileNotFoundException e) { - return false; - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - // pass - } - } - } - - return true; - } - - /** - * Creates a new store - * @param osKeyStorePath the location of the store - * @param storeType an optional keystore type, or null if the default is to - * be used. - * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr - * of the keytool process call. - * @throws KeyStoreException - * @throws NoSuchAlgorithmException - * @throws CertificateException - * @throws UnrecoverableEntryException - * @throws IOException - * @throws KeytoolException - */ - private void createNewStore(String osKeyStorePath, String storeType, IKeyGenOutput output) - throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - UnrecoverableEntryException, IOException, KeytoolException { - - if (KeystoreHelper.createNewStore(osKeyStorePath, storeType, PASSWORD_STRING, DEBUG_ALIAS, - PASSWORD_STRING, CERTIFICATE_DESC, 30 /* validity*/, output)) { - loadKeyEntry(osKeyStorePath, storeType); - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/KeystoreHelper.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/KeystoreHelper.java deleted file mode 100644 index 6ba4e723..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/KeystoreHelper.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.internal.build; - -import com.android.annotations.Nullable; -import com.android.sdklib.internal.build.DebugKeyProvider.IKeyGenOutput; -import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; - -import java.io.File; -import java.io.IOException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableEntryException; -import java.security.cert.CertificateException; -import java.util.ArrayList; - -/** - * A Helper to create new keystore/key. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public final class KeystoreHelper { - - /** - * Creates a new store - * @param osKeyStorePath the location of the store - * @param storeType an optional keystore type, or null if the default is to - * be used. - * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr - * of the keytool process call. - * @throws KeyStoreException - * @throws NoSuchAlgorithmException - * @throws CertificateException - * @throws UnrecoverableEntryException - * @throws IOException - * @throws KeytoolException - */ - public static boolean createNewStore( - String osKeyStorePath, - String storeType, - String storePassword, - String alias, - String keyPassword, - String description, - int validityYears, - final IKeyGenOutput output) - throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - UnrecoverableEntryException, IOException, KeytoolException { - - // get the executable name of keytool depending on the platform. - String os = System.getProperty("os.name"); - - String keytoolCommand; - if (os.startsWith("Windows")) { - keytoolCommand = "keytool.exe"; - } else { - keytoolCommand = "keytool"; - } - - String javaHome = System.getProperty("java.home"); - - if (javaHome != null && !javaHome.isEmpty()) { - keytoolCommand = javaHome + File.separator + "bin" + File.separator + keytoolCommand; - } - - // create the command line to call key tool to build the key with no user input. - ArrayList commandList = new ArrayList(); - commandList.add(keytoolCommand); - commandList.add("-genkey"); - commandList.add("-alias"); - commandList.add(alias); - commandList.add("-keyalg"); - commandList.add("RSA"); - commandList.add("-dname"); - commandList.add(description); - commandList.add("-validity"); - commandList.add(Integer.toString(validityYears * 365)); - commandList.add("-keypass"); - commandList.add(keyPassword); - commandList.add("-keystore"); - commandList.add(osKeyStorePath); - commandList.add("-storepass"); - commandList.add(storePassword); - if (storeType != null) { - commandList.add("-storetype"); - commandList.add(storeType); - } - - String[] commandArray = commandList.toArray(new String[commandList.size()]); - - // launch the command line process - int result = 0; - try { - Process process = Runtime.getRuntime().exec(commandArray); - result = GrabProcessOutput.grabProcessOutput( - process, - Wait.WAIT_FOR_READERS, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - if (line != null) { - if (output != null) { - output.out(line); - } else { - System.out.println(line); - } - } - } - - @Override - public void err(@Nullable String line) { - if (line != null) { - if (output != null) { - output.err(line); - } else { - System.err.println(line); - } - } - } - }); - } catch (Exception e) { - // create the command line as one string for debugging purposes - StringBuilder builder = new StringBuilder(); - boolean firstArg = true; - for (String arg : commandArray) { - boolean hasSpace = arg.indexOf(' ') != -1; - - if (firstArg == true) { - firstArg = false; - } else { - builder.append(' '); - } - - if (hasSpace) { - builder.append('"'); - } - - builder.append(arg); - - if (hasSpace) { - builder.append('"'); - } - } - - throw new KeytoolException("Failed to create key: " + e.getMessage(), - javaHome, builder.toString()); - } - - if (result != 0) { - return false; - } - - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SignedJarBuilder.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SignedJarBuilder.java deleted file mode 100644 index afb7e658..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SignedJarBuilder.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * 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.internal.build; - -import com.android.SdkConstants; -import com.android.sdklib.internal.build.SignedJarBuilder.IZipEntryFilter.ZipAbortException; - -import sun.misc.BASE64Encoder; -import sun.security.pkcs.ContentInfo; -import sun.security.pkcs.PKCS7; -import sun.security.pkcs.SignerInfo; -import sun.security.x509.AlgorithmId; -import sun.security.x509.X500Name; - -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.security.DigestOutputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.cert.X509Certificate; -import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * A Jar file builder with signature support. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public class SignedJarBuilder { - private static final String DIGEST_ALGORITHM = "SHA1"; - private static final String DIGEST_ATTR = "SHA1-Digest"; - private static final String DIGEST_MANIFEST_ATTR = "SHA1-Digest-Manifest"; - - /** Write to another stream and also feed it to the Signature object. */ - private static class SignatureOutputStream extends FilterOutputStream { - private Signature mSignature; - private int mCount = 0; - - public SignatureOutputStream(OutputStream out, Signature sig) { - super(out); - mSignature = sig; - } - - @Override - public void write(int b) throws IOException { - try { - mSignature.update((byte) b); - } catch (SignatureException e) { - throw new IOException("SignatureException: " + e); - } - super.write(b); - mCount++; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - try { - mSignature.update(b, off, len); - } catch (SignatureException e) { - throw new IOException("SignatureException: " + e); - } - super.write(b, off, len); - mCount += len; - } - - public int size() { - return mCount; - } - } - - private JarOutputStream mOutputJar; - private PrivateKey mKey; - private X509Certificate mCertificate; - private Manifest mManifest; - private BASE64Encoder mBase64Encoder; - private MessageDigest mMessageDigest; - - private byte[] mBuffer = new byte[4096]; - - /** - * Classes which implement this interface provides a method to check whether a file should - * be added to a Jar file. - */ - public interface IZipEntryFilter { - - /** - * An exception thrown during packaging of a zip file into APK file. - * This is typically thrown by implementations of - * {@link IZipEntryFilter#checkEntry(String)}. - */ - class ZipAbortException extends Exception { - private static final long serialVersionUID = 1L; - - public ZipAbortException() { - super(); - } - - public ZipAbortException(String format, Object... args) { - super(String.format(format, args)); - } - - public ZipAbortException(Throwable cause, String format, Object... args) { - super(String.format(format, args), cause); - } - - public ZipAbortException(Throwable cause) { - super(cause); - } - } - - - /** - * Checks a file for inclusion in a Jar archive. - * @param archivePath the archive file path of the entry - * @return true if the file should be included. - * @throws ZipAbortException if writing the file should be aborted. - */ - boolean checkEntry(String archivePath) throws ZipAbortException; - } - - /** - * Creates a {@link SignedJarBuilder} with a given output stream, and signing information. - *

If either key or certificate is null then - * the archive will not be signed. - * @param out the {@link OutputStream} where to write the Jar archive. - * @param key the {@link PrivateKey} used to sign the archive, or null. - * @param certificate the {@link X509Certificate} used to sign the archive, or - * null. - * @throws IOException - * @throws NoSuchAlgorithmException - */ - public SignedJarBuilder(OutputStream out, PrivateKey key, X509Certificate certificate) - throws IOException, NoSuchAlgorithmException { - mOutputJar = new JarOutputStream(new BufferedOutputStream(out)); - mOutputJar.setLevel(9); - mKey = key; - mCertificate = certificate; - - if (mKey != null && mCertificate != null) { - mManifest = new Manifest(); - Attributes main = mManifest.getMainAttributes(); - main.putValue("Manifest-Version", "1.0"); - main.putValue("Created-By", "1.0 (Android)"); - - mBase64Encoder = new BASE64Encoder(); - mMessageDigest = MessageDigest.getInstance(DIGEST_ALGORITHM); - } - } - - /** - * Writes a new {@link File} into the archive. - * @param inputFile the {@link File} to write. - * @param jarPath the filepath inside the archive. - * @throws IOException - */ - public void writeFile(File inputFile, String jarPath) throws IOException { - // Get an input stream on the file. - FileInputStream fis = new FileInputStream(inputFile); - try { - - // create the zip entry - JarEntry entry = new JarEntry(jarPath); - entry.setTime(inputFile.lastModified()); - - writeEntry(fis, entry); - } finally { - // close the file stream used to read the file - fis.close(); - } - } - - /** - * Copies the content of a Jar/Zip archive into the receiver archive. - *

An optional {@link IZipEntryFilter} allows to selectively choose which files - * to copy over. - * @param input the {@link InputStream} for the Jar/Zip to copy. - * @param filter the filter or null - * @throws IOException - * @throws ZipAbortException if the {@link IZipEntryFilter} filter indicated that the write - * must be aborted. - */ - public void writeZip(InputStream input, IZipEntryFilter filter) - throws IOException, ZipAbortException { - ZipInputStream zis = new ZipInputStream(input); - - try { - // loop on the entries of the intermediary package and put them in the final package. - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - String name = entry.getName(); - - // do not take directories or anything inside a potential META-INF folder. - if (entry.isDirectory() || name.startsWith("META-INF/")) { - continue; - } - - // if we have a filter, we check the entry against it - if (filter != null && filter.checkEntry(name) == false) { - continue; - } - - JarEntry newEntry; - - // Preserve the STORED method of the input entry. - if (entry.getMethod() == JarEntry.STORED) { - newEntry = new JarEntry(entry); - } else { - // Create a new entry so that the compressed len is recomputed. - newEntry = new JarEntry(name); - } - - writeEntry(zis, newEntry); - - zis.closeEntry(); - } - } finally { - zis.close(); - } - } - - /** - * Closes the Jar archive by creating the manifest, and signing the archive. - * @throws IOException - * @throws GeneralSecurityException - */ - public void close() throws IOException, GeneralSecurityException { - if (mManifest != null) { - // write the manifest to the jar file - mOutputJar.putNextEntry(new JarEntry(JarFile.MANIFEST_NAME)); - mManifest.write(mOutputJar); - - // CERT.SF - Signature signature = Signature.getInstance("SHA1with" + mKey.getAlgorithm()); - signature.initSign(mKey); - mOutputJar.putNextEntry(new JarEntry("META-INF/CERT.SF")); - SignatureOutputStream out = new SignatureOutputStream(mOutputJar, signature); - writeSignatureFile(out); - - // CERT.* - mOutputJar.putNextEntry(new JarEntry("META-INF/CERT." + mKey.getAlgorithm())); - writeSignatureBlock(signature, mCertificate, mKey); - - // close out at the end because it can also close mOutputJar. - // (there's some timing issue here I think, because it's worked before with out - // being closed after writing CERT.SF). - out.close(); - } - - mOutputJar.close(); - mOutputJar = null; - } - - /** - * Clean up of the builder for interrupted workflow. - * This does nothing if {@link #close()} was called successfully. - */ - public void cleanUp() { - if (mOutputJar != null) { - try { - mOutputJar.close(); - } catch (IOException e) { - // pass - } - } - } - - /** - * Adds an entry to the output jar, and write its content from the {@link InputStream} - * @param input The input stream from where to write the entry content. - * @param entry the entry to write in the jar. - * @throws IOException - */ - private void writeEntry(InputStream input, JarEntry entry) throws IOException { - // add the entry to the jar archive - mOutputJar.putNextEntry(entry); - - // read the content of the entry from the input stream, and write it into the archive. - int count; - while ((count = input.read(mBuffer)) != -1) { - mOutputJar.write(mBuffer, 0, count); - - // update the digest - if (mMessageDigest != null) { - mMessageDigest.update(mBuffer, 0, count); - } - } - - // close the entry for this file - mOutputJar.closeEntry(); - - if (mManifest != null) { - // update the manifest for this entry. - Attributes attr = mManifest.getAttributes(entry.getName()); - if (attr == null) { - attr = new Attributes(); - mManifest.getEntries().put(entry.getName(), attr); - } - attr.putValue(DIGEST_ATTR, mBase64Encoder.encode(mMessageDigest.digest())); - } - } - - /** Writes a .SF file with a digest to the manifest. */ - private void writeSignatureFile(SignatureOutputStream out) - throws IOException, GeneralSecurityException { - Manifest sf = new Manifest(); - Attributes main = sf.getMainAttributes(); - main.putValue("Signature-Version", "1.0"); - main.putValue("Created-By", "1.0 (Android)"); - - BASE64Encoder base64 = new BASE64Encoder(); - MessageDigest md = MessageDigest.getInstance(DIGEST_ALGORITHM); - PrintStream print = new PrintStream( - new DigestOutputStream(new ByteArrayOutputStream(), md), - true, SdkConstants.UTF_8); - - // Digest of the entire manifest - mManifest.write(print); - print.flush(); - main.putValue(DIGEST_MANIFEST_ATTR, base64.encode(md.digest())); - - Map entries = mManifest.getEntries(); - for (Map.Entry entry : entries.entrySet()) { - // Digest of the manifest stanza for this entry. - print.print("Name: " + entry.getKey() + "\r\n"); - for (Map.Entry att : entry.getValue().entrySet()) { - print.print(att.getKey() + ": " + att.getValue() + "\r\n"); - } - print.print("\r\n"); - print.flush(); - - Attributes sfAttr = new Attributes(); - sfAttr.putValue(DIGEST_ATTR, base64.encode(md.digest())); - sf.getEntries().put(entry.getKey(), sfAttr); - } - - sf.write(out); - - // A bug in the java.util.jar implementation of Android platforms - // up to version 1.6 will cause a spurious IOException to be thrown - // if the length of the signature file is a multiple of 1024 bytes. - // As a workaround, add an extra CRLF in this case. - if ((out.size() % 1024) == 0) { - out.write('\r'); - out.write('\n'); - } - } - - /** Write the certificate file with a digital signature. */ - private void writeSignatureBlock(Signature signature, X509Certificate publicKey, - PrivateKey privateKey) - throws IOException, GeneralSecurityException { - SignerInfo signerInfo = new SignerInfo( - new X500Name(publicKey.getIssuerX500Principal().getName()), - publicKey.getSerialNumber(), - AlgorithmId.get(DIGEST_ALGORITHM), - AlgorithmId.get(privateKey.getAlgorithm()), - signature.sign()); - - PKCS7 pkcs7 = new PKCS7( - new AlgorithmId[] { AlgorithmId.get(DIGEST_ALGORITHM) }, - new ContentInfo(ContentInfo.DATA_OID, null), - new X509Certificate[] { publicKey }, - new SignerInfo[] { signerInfo }); - - pkcs7.encodeSignedData(mOutputJar); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolLoader.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolLoader.java deleted file mode 100644 index cbb41920..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolLoader.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.build; - -import com.google.common.base.Charsets; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Table; -import com.google.common.io.Files; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -/** - * A class to load the text symbol file generated by aapt with the - * --output-text-symbols option. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public class SymbolLoader { - - private final File mSymbolFile; - private Table mSymbols; - - public static class SymbolEntry { - private final String mName; - private final String mType; - private final String mValue; - - public SymbolEntry(String name, String type, String value) { - mName = name; - mType = type; - mValue = value; - } - - public String getValue() { - return mValue; - } - - public String getName() { - return mName; - } - - public String getType() { - return mType; - } - } - - public SymbolLoader(File symbolFile) { - mSymbolFile = symbolFile; - } - - public void load() throws IOException { - List lines = Files.readLines(mSymbolFile, Charsets.UTF_8); - - mSymbols = HashBasedTable.create(); - - int lineIndex = 1; - String line = null; - try { - final int count = lines.size(); - for (; lineIndex <= count ; lineIndex++) { - line = lines.get(lineIndex-1); - - // format is " " - // don't want to split on space as value could contain spaces. - int pos = line.indexOf(' '); - String type = line.substring(0, pos); - int pos2 = line.indexOf(' ', pos + 1); - String className = line.substring(pos + 1, pos2); - int pos3 = line.indexOf(' ', pos2 + 1); - String name = line.substring(pos2 + 1, pos3); - String value = line.substring(pos3 + 1); - - mSymbols.put(className, name, new SymbolEntry(name, type, value)); - } - } catch (Exception e) { - String s = String.format("File format error reading %s\tline %d: '%s'", - mSymbolFile.getAbsolutePath(), lineIndex, line); - throw new IOException(s, e); - } - } - - Table getSymbols() { - return mSymbols; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolWriter.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolWriter.java deleted file mode 100644 index 3dfaa6fe..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/build/SymbolWriter.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.build; - -import com.android.SdkConstants; -import com.android.sdklib.internal.build.SymbolLoader.SymbolEntry; -import com.google.common.base.Charsets; -import com.google.common.base.Splitter; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Lists; -import com.google.common.collect.Table; -import com.google.common.io.Closer; -import com.google.common.io.Files; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * A class to write R.java classes based on data read from text symbol files generated by - * aapt with the --output-text-symbols option. - * - * @deprecated Use Android-Builder instead - */ -@Deprecated -public class SymbolWriter { - - private final String mOutFolder; - private final String mPackageName; - private final List mSymbols = Lists.newArrayList(); - private final SymbolLoader mValues; - - public SymbolWriter(String outFolder, String packageName, SymbolLoader values) { - mOutFolder = outFolder; - mPackageName = packageName; - mValues = values; - } - - public void addSymbolsToWrite(SymbolLoader symbols) { - mSymbols.add(symbols); - } - - private Table getAllSymbols() { - Table symbols = HashBasedTable.create(); - - for (SymbolLoader symbolLoader : mSymbols) { - symbols.putAll(symbolLoader.getSymbols()); - } - - return symbols; - } - - public void write() throws IOException { - Splitter splitter = Splitter.on('.'); - Iterable folders = splitter.split(mPackageName); - File file = new File(mOutFolder); - for (String folder : folders) { - file = new File(file, folder); - } - file.mkdirs(); - file = new File(file, SdkConstants.FN_RESOURCE_CLASS); - - Closer closer = Closer.create(); - try { - BufferedWriter writer = closer.register(Files.newWriter(file, Charsets.UTF_8)); - - writer.write("/* AUTO-GENERATED FILE. DO NOT MODIFY.\n"); - writer.write(" *\n"); - writer.write(" * This class was automatically generated by the\n"); - writer.write(" * aapt tool from the resource data it found. It\n"); - writer.write(" * should not be modified by hand.\n"); - writer.write(" */\n"); - - writer.write("package "); - writer.write(mPackageName); - writer.write(";\n\npublic final class R {\n"); - - Table symbols = getAllSymbols(); - Table values = mValues.getSymbols(); - - Set rowSet = symbols.rowKeySet(); - List rowList = Lists.newArrayList(rowSet); - Collections.sort(rowList); - - for (String row : rowList) { - writer.write("\tpublic static final class "); - writer.write(row); - writer.write(" {\n"); - - Map rowMap = symbols.row(row); - Set symbolSet = rowMap.keySet(); - ArrayList symbolList = Lists.newArrayList(symbolSet); - Collections.sort(symbolList); - - for (String symbolName : symbolList) { - // get the matching SymbolEntry from the values Table. - SymbolEntry value = values.get(row, symbolName); - if (value != null) { - writer.write("\t\tpublic static final "); - writer.write(value.getType()); - writer.write(" "); - writer.write(value.getName()); - writer.write(" = "); - writer.write(value.getValue()); - writer.write(";\n"); - } - } - - writer.write("\t}\n"); - } - - writer.write("}\n"); - } catch (Throwable e) { - throw closer.rethrow(e); - } finally { - closer.close(); - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectCreator.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectCreator.java deleted file mode 100644 index c5712d75..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectCreator.java +++ /dev/null @@ -1,1571 +0,0 @@ -/* - * 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.internal.project; - -import com.android.SdkConstants; -import com.android.io.FileWrapper; -import com.android.io.FolderWrapper; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.project.ProjectProperties.PropertyType; -import com.android.utils.ILogger; -import com.android.xml.AndroidManifest; -import com.android.xml.AndroidXPathFactory; - -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - -/** - * Creates the basic files needed to get an Android project up and running. - */ -public class ProjectCreator { - - /** Version of the build.xml. Stored in version-tag */ - private static final int MIN_BUILD_VERSION_TAG = 1; - - /** Package path substitution string used in template files, i.e. "PACKAGE_PATH" */ - private static final String PH_PACKAGE_PATH = "PACKAGE_PATH"; - /** Package name substitution string used in template files, i.e. "PACKAGE" */ - private static final String PH_PACKAGE = "PACKAGE"; - /** Activity name substitution string used in template files, i.e. "ACTIVITY_NAME". - * @deprecated This is only used for older templates. For new ones see - * {@link #PH_ACTIVITY_ENTRY_NAME}, and {@link #PH_ACTIVITY_CLASS_NAME}. */ - @Deprecated - private static final String PH_ACTIVITY_NAME = "ACTIVITY_NAME"; - /** Activity name substitution string used in manifest templates, i.e. "ACTIVITY_ENTRY_NAME".*/ - private static final String PH_ACTIVITY_ENTRY_NAME = "ACTIVITY_ENTRY_NAME"; - /** Activity name substitution string used in class templates, i.e. "ACTIVITY_CLASS_NAME".*/ - private static final String PH_ACTIVITY_CLASS_NAME = "ACTIVITY_CLASS_NAME"; - /** Activity FQ-name substitution string used in class templates, i.e. "ACTIVITY_FQ_NAME".*/ - private static final String PH_ACTIVITY_FQ_NAME = "ACTIVITY_FQ_NAME"; - /** Original Activity class name substitution string used in class templates, i.e. - * "ACTIVITY_TESTED_CLASS_NAME".*/ - private static final String PH_ACTIVITY_TESTED_CLASS_NAME = "ACTIVITY_TESTED_CLASS_NAME"; - /** Project name substitution string used in template files, i.e. "PROJECT_NAME". */ - public static final String PH_PROJECT_NAME = "PROJECT_NAME"; - /** Application icon substitution string used in the manifest template */ - private static final String PH_ICON = "ICON"; - /** Version tag name substitution string used in template files, i.e. "VERSION_TAG". */ - private static final String PH_VERSION_TAG = "VERSION_TAG"; - /** Target name substitution string used in template files, i.e. "TARGET". */ - private static final String PH_TARGET = "TARGET"; - /** Gradle plugin substitution string used in the build.gradle template */ - private static final String PH_PLUGIN = "PLUGIN"; - /** Gradle artifact version substitution string used in the build.gradle template */ - private static final String PH_ARTIFACT_VERSION = "ARTIFACT_VERSION"; - /** Build tool revision substitution string used in the build.gradle template */ - private static final String PH_BUILD_TOOL_REV = "BUILD_TOOL_REV"; - - /** The xpath to find a project name in an Ant build file. */ - private static final String XPATH_PROJECT_NAME = "/project/@name"; - - /** Pattern for characters accepted in a project name. Since this will be used as a - * directory name, we're being a bit conservative on purpose: dot and space cannot be used. */ - public static final Pattern RE_PROJECT_NAME = Pattern.compile("[a-zA-Z0-9_]+"); - /** List of valid characters for a project name. Used for display purposes. */ - public static final String CHARS_PROJECT_NAME = "a-z A-Z 0-9 _"; - - /** Pattern for characters accepted in a package name. A package is list of Java identifier - * separated by a dot. We need to have at least one dot (e.g. a two-level package name). - * A Java identifier cannot start by a digit. */ - public static final Pattern RE_PACKAGE_NAME = - Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)+"); - /** List of valid characters for a project name. Used for display purposes. */ - public static final String CHARS_PACKAGE_NAME = "a-z A-Z 0-9 _"; - - /** Pattern for characters accepted in an activity name, which is a Java identifier. */ - public static final Pattern RE_ACTIVITY_NAME = - Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*"); - /** List of valid characters for a project name. Used for display purposes. */ - public static final String CHARS_ACTIVITY_NAME = "a-z A-Z 0-9 _"; - - /** Gradle plugin to use with standard projects */ - private static final String PLUGIN_PROJECT = "android"; - /** Gradle plugin to use with library projects */ - private static final String PLUGIN_LIB_PROJECT = "android-library"; - - - public enum OutputLevel { - /** Silent mode. Project creation will only display errors. */ - SILENT, - /** Normal mode. Project creation will display what's being done, display - * error but not warnings. */ - NORMAL, - /** Verbose mode. Project creation will display what's being done, errors and warnings. */ - VERBOSE - } - - /** - * Exception thrown when a project creation fails, typically because a template - * file cannot be written. - */ - private static class ProjectCreateException extends Exception { - /** default UID. This will not be serialized anyway. */ - private static final long serialVersionUID = 1L; - - @SuppressWarnings("unused") - ProjectCreateException(String message) { - super(message); - } - - ProjectCreateException(Throwable t, String format, Object... args) { - super(format != null ? String.format(format, args) : format, t); - } - - ProjectCreateException(String format, Object... args) { - super(String.format(format, args)); - } - } - - /** The {@link OutputLevel} verbosity. */ - private final OutputLevel mLevel; - /** Logger for errors and output. Cannot be null. */ - private final ILogger mLog; - /** The OS path of the SDK folder. */ - private final String mSdkFolder; - /** The {@link SdkManager} instance. */ - private final SdkManager mSdkManager; - - /** - * Helper class to create android projects. - * - * @param sdkManager The {@link SdkManager} instance. - * @param sdkFolder The OS path of the SDK folder. - * @param level The {@link OutputLevel} verbosity. - * @param log Logger for errors and output. Cannot be null. - */ - public ProjectCreator(SdkManager sdkManager, String sdkFolder, OutputLevel level, ILogger log) { - mSdkManager = sdkManager; - mSdkFolder = sdkFolder; - mLevel = level; - mLog = log; - } - - /** - * Creates a new (ant) project. - *

- * The caller should have already checked and sanitized the parameters. - * - * @param folderPath the folder of the project to create. - * @param projectName the name of the project. The name must match the - * {@link #RE_PROJECT_NAME} regex. - * @param packageName the package of the project. The name must match the - * {@link #RE_PACKAGE_NAME} regex. - * @param activityEntry the activity of the project as it will appear in the manifest. Can be - * null if no activity should be created. The name must match the - * {@link #RE_ACTIVITY_NAME} regex. - * @param target the project target. - * @param library whether the project is a library. - * @param pathToMainProject if non-null the project will be setup to test a main project - * located at the given path. - */ - public void createProject(String folderPath, String projectName, - String packageName, String activityEntry, IAndroidTarget target, boolean library, - String pathToMainProject) { - - // create project folder if it does not exist - File projectFolder = checkNewProjectLocation(folderPath); - if (projectFolder == null) { - return; - } - - try { - boolean isTestProject = pathToMainProject != null; - - // first create the project properties. - - // location of the SDK goes in localProperty - ProjectPropertiesWorkingCopy localProperties = ProjectProperties.create(folderPath, - PropertyType.LOCAL); - localProperties.setProperty(ProjectProperties.PROPERTY_SDK, mSdkFolder); - localProperties.save(); - - // target goes in project properties - ProjectPropertiesWorkingCopy projectProperties = ProjectProperties.create(folderPath, - PropertyType.PROJECT); - projectProperties.setProperty(ProjectProperties.PROPERTY_TARGET, target.hashString()); - if (library) { - projectProperties.setProperty(ProjectProperties.PROPERTY_LIBRARY, "true"); - } - projectProperties.save(); - - // create a ant.properties file with just the application package - ProjectPropertiesWorkingCopy antProperties = ProjectProperties.create(folderPath, - PropertyType.ANT); - - if (isTestProject) { - antProperties.setProperty(ProjectProperties.PROPERTY_TESTED_PROJECT, - pathToMainProject); - } - - antProperties.save(); - - // create the map for place-holders of values to replace in the templates - final HashMap keywords = new HashMap(); - - // create the required folders. - // compute src folder path - final String packagePath = - stripString(packageName.replace(".", File.separator), - File.separatorChar); - - // put this path in the place-holder map for project files that needs to list - // files manually. - keywords.put(PH_PACKAGE_PATH, packagePath); - keywords.put(PH_PACKAGE, packageName); - keywords.put(PH_VERSION_TAG, Integer.toString(MIN_BUILD_VERSION_TAG)); - - - // compute some activity related information - String fqActivityName = null, activityPath = null, activityClassName = null; - String originalActivityEntry = activityEntry; - String originalActivityClassName = null; - if (activityEntry != null) { - if (isTestProject) { - // append Test so that it doesn't collide with the main project activity. - activityEntry += "Test"; - - // get the classname from the original activity entry. - int pos = originalActivityEntry.lastIndexOf('.'); - if (pos != -1) { - originalActivityClassName = originalActivityEntry.substring(pos + 1); - } else { - originalActivityClassName = originalActivityEntry; - } - } - - // get the fully qualified name of the activity - fqActivityName = AndroidManifest.combinePackageAndClassName(packageName, - activityEntry); - - // get the activity path (replace the . to /) - activityPath = stripString(fqActivityName.replace(".", File.separator), - File.separatorChar); - - // remove the last segment, so that we only have the path to the activity, but - // not the activity filename itself. - activityPath = activityPath.substring(0, - activityPath.lastIndexOf(File.separatorChar)); - - // finally, get the class name for the activity - activityClassName = fqActivityName.substring(fqActivityName.lastIndexOf('.') + 1); - } - - // at this point we have the following for the activity: - // activityEntry: this is the manifest entry. For instance .MyActivity - // fqActivityName: full-qualified class name: com.foo.MyActivity - // activityClassName: only the classname: MyActivity - // originalActivityClassName: the classname of the activity being tested (if applicable) - - // Add whatever activity info is needed in the place-holder map. - // Older templates only expect ACTIVITY_NAME to be the same (and unmodified for tests). - if (target.getVersion().getApiLevel() < 4) { // legacy - if (originalActivityEntry != null) { - keywords.put(PH_ACTIVITY_NAME, originalActivityEntry); - } - } else { - // newer templates make a difference between the manifest entries, classnames, - // as well as the main and test classes. - if (activityEntry != null) { - keywords.put(PH_ACTIVITY_ENTRY_NAME, activityEntry); - keywords.put(PH_ACTIVITY_CLASS_NAME, activityClassName); - keywords.put(PH_ACTIVITY_FQ_NAME, fqActivityName); - if (originalActivityClassName != null) { - keywords.put(PH_ACTIVITY_TESTED_CLASS_NAME, originalActivityClassName); - } - } - } - - // Take the project name from the command line if there's one - if (projectName != null) { - keywords.put(PH_PROJECT_NAME, projectName); - } else { - if (activityClassName != null) { - // Use the activity class name as project name - keywords.put(PH_PROJECT_NAME, activityClassName); - } else { - // We need a project name. Just pick up the basename of the project - // directory. - projectName = projectFolder.getName(); - keywords.put(PH_PROJECT_NAME, projectName); - } - } - - // create the source folder for the activity - if (activityClassName != null) { - String srcActivityFolderPath = - SdkConstants.FD_SOURCES + File.separator + activityPath; - File sourceFolder = createDirs(projectFolder, srcActivityFolderPath); - - String javaTemplate = isTestProject ? "java_tests_file.template" - : "java_file.template"; - String activityFileName = activityClassName + ".java"; - - installTargetTemplate(javaTemplate, new File(sourceFolder, activityFileName), - keywords, target); - } else { - // we should at least create 'src' - createDirs(projectFolder, SdkConstants.FD_SOURCES); - } - - // create other useful folders - File resourceFolder = createDirs(projectFolder, SdkConstants.FD_RESOURCES); - createDirs(projectFolder, SdkConstants.FD_OUTPUT); - createDirs(projectFolder, SdkConstants.FD_NATIVE_LIBS); - - if (isTestProject == false) { - /* Make res files only for non test projects */ - File valueFolder = createDirs(resourceFolder, SdkConstants.FD_RES_VALUES); - installTargetTemplate("strings.template", new File(valueFolder, "strings.xml"), - keywords, target); - - File layoutFolder = createDirs(resourceFolder, SdkConstants.FD_RES_LAYOUT); - installTargetTemplate("layout.template", new File(layoutFolder, "main.xml"), - keywords, target); - - // create the icons - if (installIcons(resourceFolder, target)) { - keywords.put(PH_ICON, "android:icon=\"@drawable/ic_launcher\""); - } else { - keywords.put(PH_ICON, ""); - } - } - - /* Make AndroidManifest.xml and build.xml files */ - String manifestTemplate = "AndroidManifest.template"; - if (isTestProject) { - manifestTemplate = "AndroidManifest.tests.template"; - } - - installTargetTemplate(manifestTemplate, - new File(projectFolder, SdkConstants.FN_ANDROID_MANIFEST_XML), - keywords, target); - - installTemplate("build.template", - new File(projectFolder, SdkConstants.FN_BUILD_XML), - keywords); - - // install the proguard config file. - installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE, - new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE), - null /*keywords*/); - } catch (Exception e) { - mLog.error(e, null); - } - } - - /** - * Creates a new (gradle) project. - *

- * The caller should have already checked and sanitized the parameters. - * - * @param folderPath the folder of the project to create. - * @param projectName the name of the project. The name must match the - * {@link #RE_PROJECT_NAME} regex. - * @param packageName the package of the project. The name must match the - * {@link #RE_PACKAGE_NAME} regex. - * @param activityEntry the activity of the project as it will appear in the manifest. Can be - * null if no activity should be created. The name must match the - * {@link #RE_ACTIVITY_NAME} regex. - * @param target the project target. - * @param library whether the project is a library. - * @param artifactVersion the version of the gradle artifact in maven. - */ - public void createGradleProject(String folderPath, String projectName, - String packageName, String activityEntry, IAndroidTarget target, boolean library, - String artifactVersion) { - - // create project folder if it does not exist - File projectFolder = checkNewProjectLocation(folderPath); - if (projectFolder == null) { - return; - } - - try { - // first create the project properties. - - // location of the SDK goes in localProperty - ProjectPropertiesWorkingCopy localProperties = ProjectProperties.create(folderPath, - PropertyType.LOCAL); - localProperties.setProperty(ProjectProperties.PROPERTY_SDK, mSdkFolder); - localProperties.save(); - - // create the map for place-holders of values to replace in the templates - final HashMap keywords = new HashMap(); - final HashMap testKeywords = new HashMap(); - - // create the required folders. - // compute src folder path - final String packagePath = - stripString(packageName.replace(".", File.separator), - File.separatorChar); - - // put this path in the place-holder map for project files that needs to list - // files manually. - keywords.put(PH_PACKAGE_PATH, packagePath); - keywords.put(PH_PACKAGE, packageName); - - testKeywords.put(PH_PACKAGE_PATH, packagePath); - testKeywords.put(PH_PACKAGE, packageName); - - // compute some activity related information - String activityPath = null, activityClassName = null; - String testActivityPath = null, testActivityClassName = null; - if (activityEntry != null) { - // get the fully qualified name of the activity - String fqActivityName = AndroidManifest.combinePackageAndClassName(packageName, - activityEntry); - - // get the activity path (replace the . to /) - activityPath = stripString(fqActivityName.replace(".", File.separator), - File.separatorChar); - - // remove the last segment, so that we only have the path to the activity, but - // not the activity filename itself. - activityPath = activityPath.substring(0, - activityPath.lastIndexOf(File.separatorChar)); - - // finally, get the class name for the activity - activityClassName = fqActivityName.substring(fqActivityName.lastIndexOf('.') + 1); - - // at this point we have the following for the activity: - // activityEntry: this is the manifest entry. For instance .MyActivity - // fqActivityName: full-qualified class name: com.foo.MyActivity - // activityClassName: only the classname: MyActivity - - // append Test so that it doesn't collide with the main project activity. - String testActivityEntry = activityEntry + "Test"; - - // get the fully qualified name of the test - String testFqActivityName = AndroidManifest.combinePackageAndClassName(packageName, - testActivityEntry); - - // get the test path (replace the . to /) - testActivityPath = stripString(testFqActivityName.replace(".", File.separator), - File.separatorChar); - - // remove the last segment, so that we only have the path to the test, but - // not the test filename itself. - testActivityPath = testActivityPath.substring(0, - testActivityPath.lastIndexOf(File.separatorChar)); - - // finally, get the class name for the test - testActivityClassName = testFqActivityName.substring(testFqActivityName.lastIndexOf('.') + 1); - - // at this point we have the following for the test: - // testActivityEntry: this is the manifest entry. For instance .MyActivityTest - // testFqActivityName: full-qualified class name: com.foo.MyActivityTest - // testActivityClassName: only the classname: MyActivityTest - - // Add whatever activity info is needed in the place-holder map. - // Older templates only expect ACTIVITY_NAME to be the same (and unmodified for tests). - if (target.getVersion().getApiLevel() < 4) { // legacy - keywords.put(PH_ACTIVITY_NAME, activityEntry); - testKeywords.put(PH_ACTIVITY_NAME, activityEntry); - } else { - // newer templates make a difference between the manifest entries, classnames, - // as well as the main and test classes. - keywords.put(PH_ACTIVITY_ENTRY_NAME, activityEntry); - keywords.put(PH_ACTIVITY_CLASS_NAME, activityClassName); - keywords.put(PH_ACTIVITY_FQ_NAME, fqActivityName); - - testKeywords.put(PH_ACTIVITY_ENTRY_NAME, testActivityEntry); - testKeywords.put(PH_ACTIVITY_CLASS_NAME, testActivityClassName); - testKeywords.put(PH_ACTIVITY_FQ_NAME, testFqActivityName); - testKeywords.put(PH_ACTIVITY_TESTED_CLASS_NAME, activityClassName); - } - } - - // Take the project name from the command line if there's one - if (projectName != null) { - keywords.put(PH_PROJECT_NAME, projectName); - testKeywords.put(PH_PROJECT_NAME, projectName); - } else { - // Use the activity class name as project name, else just - // pick up the basename of the project directory. - keywords.put(PH_PROJECT_NAME, (activityClassName != null) ? - activityClassName : projectFolder.getName()); - testKeywords.put(PH_PROJECT_NAME, (testActivityClassName != null) ? - testActivityClassName : projectFolder.getName()); - } - - String srcMainPath = SdkConstants.FD_SOURCES + File.separator + - SdkConstants.FD_MAIN; - String srcTestPath = SdkConstants.FD_SOURCES + File.separator + - SdkConstants.FD_TEST; - - // create the source folders for the activity - String srcMainCodePath = srcMainPath + File.separator + SdkConstants.FD_JAVA; - createDirs(projectFolder, srcMainCodePath); - if (activityClassName != null) { - String srcActivityFolderPath = - srcMainCodePath + File.separator + activityPath; - File sourceFolder = createDirs(projectFolder, srcActivityFolderPath); - - String activityFileName = activityClassName + ".java"; - - installTargetTemplate("java_file.template", - new File(sourceFolder, activityFileName), keywords, target); - } - - // create the source folders for the test - String srcTestCodePath = srcTestPath + File.separator + SdkConstants.FD_JAVA; - createDirs(projectFolder, srcTestCodePath); - if (testActivityClassName != null) { - String srcActivityFolderPath = - srcTestCodePath + File.separator + testActivityPath; - File sourceFolder = createDirs(projectFolder, srcActivityFolderPath); - - String activityFileName = testActivityClassName + ".java"; - - installTargetTemplate("java_tests_file.template", - new File(sourceFolder, activityFileName), testKeywords, target); - } - - // create the res xml files - String srcMainResPath = srcMainPath + File.separator + SdkConstants.FD_RES; - File resourceFolder = createDirs(projectFolder, srcMainResPath); - - File valueFolder = createDirs(resourceFolder, SdkConstants.FD_RES_VALUES); - installTargetTemplate("strings.template", new File(valueFolder, "strings.xml"), - keywords, target); - - File layoutFolder = createDirs(resourceFolder, SdkConstants.FD_RES_LAYOUT); - installTargetTemplate("layout.template", new File(layoutFolder, "main.xml"), - keywords, target); - - // create the icons - if (installIcons(resourceFolder, target)) { - keywords.put(PH_ICON, "android:icon=\"@drawable/ic_launcher\""); - } else { - keywords.put(PH_ICON, ""); - } - - // Create the AndroidManifest.xml and build.gradle files - installTargetTemplate("AndroidManifest.template", - new File(projectFolder, srcMainPath + File.separator + - SdkConstants.FN_ANDROID_MANIFEST_XML), - keywords, target); - - String buildToolRev = mSdkManager.getLatestBuildTool().getRevision().toString(); - - keywords.put(PH_BUILD_TOOL_REV, buildToolRev); - keywords.put(PH_ARTIFACT_VERSION, artifactVersion); - keywords.put(PH_TARGET, target.hashString()); - keywords.put(PH_PLUGIN, (library) ? PLUGIN_LIB_PROJECT : PLUGIN_PROJECT); - - installTemplate("build_gradle.template", - new File(projectFolder, SdkConstants.FN_BUILD_GRADLE), - keywords); - - // Create the gradle wrapper files - createDirs(projectFolder, SdkConstants.FD_GRADLE_WRAPPER); - installGradleWrapperFile(SdkConstants.FD_GRADLE_WRAPPER + File.separator - + SdkConstants.FN_GRADLE_WRAPPER_JAR, - projectFolder); - installGradleWrapperFile(SdkConstants.FD_GRADLE_WRAPPER + File.separator - + SdkConstants.FN_GRADLE_WRAPPER_PROPERTIES, - projectFolder); - installGradleWrapperFile(SdkConstants.FN_GRADLE_WRAPPER_WIN, projectFolder); - installGradleWrapperFile(SdkConstants.FN_GRADLE_WRAPPER_UNIX, projectFolder); - new File(projectFolder, SdkConstants.FN_GRADLE_WRAPPER_UNIX).setExecutable(true, false); - } catch (Exception e) { - mLog.error(e, null); - } - } - - private File checkNewProjectLocation(String folderPath) { - File projectFolder = new File(folderPath); - if (!projectFolder.exists()) { - - boolean created = false; - Throwable t = null; - try { - created = projectFolder.mkdirs(); - } catch (Exception e) { - t = e; - } - - if (created) { - println("Created project directory: %1$s", projectFolder); - } else { - mLog.error(t, "Could not create directory: %1$s", projectFolder); - return null; - } - } else { - Exception e = null; - String error = null; - try { - String[] content = projectFolder.list(); - if (content == null) { - error = "Project folder '%1$s' is not a directory."; - } else if (content.length != 0) { - error = "Project folder '%1$s' is not empty. Please consider using '%2$s update' instead."; - } - } catch (Exception e1) { - e = e1; - } - - if (e != null || error != null) { - mLog.error(e, error, projectFolder, SdkConstants.androidCmdName()); - } - } - return projectFolder; - } - - /** - * Updates an existing project. - *

- * Workflow: - *

    - *
  • Check AndroidManifest.xml is present (required) - *
  • Check if there's a legacy properties file and convert it - *
  • Check there's a project.properties with a target *or* --target was specified - *
  • Update default.prop if --target was specified - *
  • Refresh/create "sdk" in local.properties - *
  • Build.xml: create if not present or if version-tag is found or not. version-tag:custom - * prevent any overwrite. version-tag:[integer] will override. missing version-tag will query - * the dev. - *
- * - * @param folderPath the folder of the project to update. This folder must exist. - * @param target the project target. Can be null. - * @param projectName The project name from --name. Can be null. - * @param libraryPath the path to a library to add to the references. Can be null. - * @return true if the project was successfully updated. - */ - @SuppressWarnings("deprecation") - public boolean updateProject(String folderPath, IAndroidTarget target, String projectName, - String libraryPath) { - // since this is an update, check the folder does point to a project - FileWrapper androidManifest = checkProjectFolder(folderPath, - SdkConstants.FN_ANDROID_MANIFEST_XML); - if (androidManifest == null) { - return false; - } - - // get the parent folder. - FolderWrapper projectFolder = (FolderWrapper) androidManifest.getParentFolder(); - - boolean hasProguard = false; - - // Check there's a project.properties with a target *or* --target was specified - IAndroidTarget originalTarget = null; - boolean writeProjectProp = false; - ProjectProperties props = ProjectProperties.load(projectFolder, PropertyType.PROJECT); - - if (props == null) { - // no project.properties, try to load default.properties - props = ProjectProperties.load(projectFolder, PropertyType.LEGACY_DEFAULT); - writeProjectProp = true; - } - - if (props != null) { - String targetHash = props.getProperty(ProjectProperties.PROPERTY_TARGET); - originalTarget = mSdkManager.getTargetFromHashString(targetHash); - - // if the project is already setup with proguard, we won't copy the proguard config. - hasProguard = props.getProperty(ProjectProperties.PROPERTY_PROGUARD_CONFIG) != null; - } - - if (originalTarget == null && target == null) { - mLog.error(null, - "The project either has no target set or the target is invalid.\n" + - "Please provide a --target to the '%1$s update' command.", - SdkConstants.androidCmdName()); - return false; - } - - boolean saveProjectProps = false; - - ProjectPropertiesWorkingCopy propsWC = null; - - // Update default.prop if --target was specified - if (target != null || writeProjectProp) { - // we already attempted to load the file earlier, if that failed, create it. - if (props == null) { - propsWC = ProjectProperties.create(projectFolder, PropertyType.PROJECT); - } else { - propsWC = props.makeWorkingCopy(PropertyType.PROJECT); - } - - // set or replace the target - if (target != null) { - propsWC.setProperty(ProjectProperties.PROPERTY_TARGET, target.hashString()); - } - saveProjectProps = true; - } - - if (libraryPath != null) { - // At this point, the default properties already exists, either because they were - // already there or because they were created with a new target - if (propsWC == null) { - assert props != null; - propsWC = props.makeWorkingCopy(); - } - - // check the reference is valid - File libProject = new File(libraryPath); - String resolvedPath; - if (libProject.isAbsolute() == false) { - libProject = new File(projectFolder, libraryPath); - try { - resolvedPath = libProject.getCanonicalPath(); - } catch (IOException e) { - mLog.error(e, "Unable to resolve path to library project: %1$s", libraryPath); - return false; - } - } else { - resolvedPath = libProject.getAbsolutePath(); - } - - println("Resolved location of library project to: %1$s", resolvedPath); - - // check the lib project exists - if (checkProjectFolder(resolvedPath, SdkConstants.FN_ANDROID_MANIFEST_XML) == null) { - mLog.error(null, "No Android Manifest at: %1$s", resolvedPath); - return false; - } - - // look for other references to figure out the index - int index = 1; - while (true) { - String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index); - assert props != null; - if (props == null) { - // This should not happen yet SDK bug 20535 says it can, not sure how. - break; - } - String ref = props.getProperty(propName); - if (ref == null) { - break; - } else { - index++; - } - } - - String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index); - propsWC.setProperty(propName, libraryPath); - saveProjectProps = true; - } - - // save the default props if needed. - if (saveProjectProps) { - try { - assert propsWC != null; - propsWC.save(); - if (writeProjectProp) { - println("Updated and renamed %1$s to %2$s", - PropertyType.LEGACY_DEFAULT.getFilename(), - PropertyType.PROJECT.getFilename()); - } else { - println("Updated %1$s", PropertyType.PROJECT.getFilename()); - } - } catch (Exception e) { - mLog.error(e, "Failed to write %1$s file in '%2$s'", - PropertyType.PROJECT.getFilename(), - folderPath); - return false; - } - - if (writeProjectProp) { - // need to delete the default prop file. - ProjectProperties.delete(projectFolder, PropertyType.LEGACY_DEFAULT); - } - } - - // Refresh/create "sdk" in local.properties - // because the file may already exists and contain other values (like apk config), - // we first try to load it. - props = ProjectProperties.load(projectFolder, PropertyType.LOCAL); - if (props == null) { - propsWC = ProjectProperties.create(projectFolder, PropertyType.LOCAL); - } else { - propsWC = props.makeWorkingCopy(); - } - - // set or replace the sdk location. - propsWC.setProperty(ProjectProperties.PROPERTY_SDK, mSdkFolder); - try { - propsWC.save(); - println("Updated %1$s", PropertyType.LOCAL.getFilename()); - } catch (Exception e) { - mLog.error(e, "Failed to write %1$s file in '%2$s'", - PropertyType.LOCAL.getFilename(), - folderPath); - return false; - } - - // legacy: check if build.properties must be renamed to ant.properties. - props = ProjectProperties.load(projectFolder, PropertyType.ANT); - if (props == null) { - props = ProjectProperties.load(projectFolder, PropertyType.LEGACY_BUILD); - if (props != null) { - try { - // get a working copy with the new property type - propsWC = props.makeWorkingCopy(PropertyType.ANT); - propsWC.save(); - - // delete the old file - ProjectProperties.delete(projectFolder, PropertyType.LEGACY_BUILD); - - println("Renamed %1$s to %2$s", - PropertyType.LEGACY_BUILD.getFilename(), - PropertyType.ANT.getFilename()); - } catch (Exception e) { - mLog.error(e, "Failed to write %1$s file in '%2$s'", - PropertyType.ANT.getFilename(), - folderPath); - return false; - } - } - } - - // Build.xml: create if not present or no in it - File buildXml = new File(projectFolder, SdkConstants.FN_BUILD_XML); - boolean needsBuildXml = projectName != null || !buildXml.exists(); - - // if it seems there's no need for a new build.xml, look for inside the file - // to try to detect old ones that may need updating. - if (!needsBuildXml) { - // we are looking for version-tag: followed by either an integer or "custom". - if (checkFileContainsRegexp(buildXml, "version-tag:\\s*custom") != null) { //$NON-NLS-1$ - println("%1$s: Found version-tag: custom. File will not be updated.", - SdkConstants.FN_BUILD_XML); - } else { - Matcher m = checkFileContainsRegexp(buildXml, "version-tag:\\s*(\\d+)"); //$NON-NLS-1$ - if (m == null) { - println("----------\n" + - "%1$s: Failed to find version-tag string. File must be updated.\n" + - "In order to not erase potential customizations, the file will not be automatically regenerated.\n" + - "If no changes have been made to the file, delete it manually and run the command again.\n" + - "If you have made customizations to the build process, the file must be manually updated.\n" + - "It is recommended to:\n" + - "\t* Copy current file to a safe location.\n" + - "\t* Delete original file.\n" + - "\t* Run command again to generate a new file.\n" + - "\t* Port customizations to the new file, by looking at the new rules file\n" + - "\t located at /tools/ant/build.xml\n" + - "\t* Update file to contain\n" + - "\t version-tag: custom\n" + - "\t to prevent file from being rewritten automatically by the SDK tools.\n" + - "----------\n", - SdkConstants.FN_BUILD_XML); - } else { - String versionStr = m.group(1); - if (versionStr != null) { - // can't fail due to regexp above. - int version = Integer.parseInt(versionStr); - if (version < MIN_BUILD_VERSION_TAG) { - println("%1$s: Found version-tag: %2$d. Expected version-tag: %3$d: file must be updated.", - SdkConstants.FN_BUILD_XML, version, MIN_BUILD_VERSION_TAG); - needsBuildXml = true; - } - } - } - } - } - - if (needsBuildXml) { - // create the map for place-holders of values to replace in the templates - final HashMap keywords = new HashMap(); - - // put the current version-tag value - keywords.put(PH_VERSION_TAG, Integer.toString(MIN_BUILD_VERSION_TAG)); - - // if there was no project name on the command line, figure one out. - if (projectName == null) { - // otherwise, take it from the existing build.xml if it exists already. - if (buildXml.exists()) { - try { - XPathFactory factory = XPathFactory.newInstance(); - XPath xpath = factory.newXPath(); - - projectName = xpath.evaluate(XPATH_PROJECT_NAME, - new InputSource(new FileInputStream(buildXml))); - } catch (XPathExpressionException e) { - // this is ok since we're going to recreate the file. - mLog.error(e, "Unable to find existing project name from %1$s", - SdkConstants.FN_BUILD_XML); - } catch (FileNotFoundException e) { - // can't happen since we check above. - } - } - - // if the project is still null, then we find another way. - if (projectName == null) { - extractPackageFromManifest(androidManifest, keywords); - if (keywords.containsKey(PH_ACTIVITY_ENTRY_NAME)) { - String activity = keywords.get(PH_ACTIVITY_ENTRY_NAME); - // keep only the last segment if applicable - int pos = activity.lastIndexOf('.'); - if (pos != -1) { - activity = activity.substring(pos + 1); - } - - // Use the activity as project name - projectName = activity; - - println("No project name specified, using Activity name '%1$s'.\n" + - "If you wish to change it, edit the first line of %2$s.", - activity, SdkConstants.FN_BUILD_XML); - } else { - // We need a project name. Just pick up the basename of the project - // directory. - File projectCanonicalFolder = projectFolder; - try { - projectCanonicalFolder = projectCanonicalFolder.getCanonicalFile(); - } catch (IOException e) { - // ignore, keep going - } - - // Use the folder name as project name - projectName = projectCanonicalFolder.getName(); - - println("No project name specified, using project folder name '%1$s'.\n" + - "If you wish to change it, edit the first line of %2$s.", - projectName, SdkConstants.FN_BUILD_XML); - } - } - } - - // put the project name in the map for replacement during the template installation. - keywords.put(PH_PROJECT_NAME, projectName); - - if (mLevel == OutputLevel.VERBOSE) { - println("Regenerating %1$s with project name %2$s", - SdkConstants.FN_BUILD_XML, - keywords.get(PH_PROJECT_NAME)); - } - - try { - installTemplate("build.template", buildXml, keywords); - } catch (ProjectCreateException e) { - mLog.error(e, null); - return false; - } - } - - if (hasProguard == false) { - try { - installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE, - // Write ProGuard config files with the extension .pro which - // is what is used in the ProGuard documentation and samples - new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE), - null /*placeholderMap*/); - } catch (ProjectCreateException e) { - mLog.error(e, null); - return false; - } - } - - return true; - } - - /** - * Updates a test project with a new path to the main (tested) project. - * @param folderPath the path of the test project. - * @param pathToMainProject the path to the main project, relative to the test project. - */ - @SuppressWarnings("deprecation") - public void updateTestProject(final String folderPath, final String pathToMainProject, - final SdkManager sdkManager) { - // since this is an update, check the folder does point to a project - if (checkProjectFolder(folderPath, SdkConstants.FN_ANDROID_MANIFEST_XML) == null) { - return; - } - - // check the path to the main project is valid. - File mainProject = new File(pathToMainProject); - String resolvedPath; - if (mainProject.isAbsolute() == false) { - mainProject = new File(folderPath, pathToMainProject); - try { - resolvedPath = mainProject.getCanonicalPath(); - } catch (IOException e) { - mLog.error(e, "Unable to resolve path to main project: %1$s", pathToMainProject); - return; - } - } else { - resolvedPath = mainProject.getAbsolutePath(); - } - - println("Resolved location of main project to: %1$s", resolvedPath); - - // check the main project exists - if (checkProjectFolder(resolvedPath, SdkConstants.FN_ANDROID_MANIFEST_XML) == null) { - mLog.error(null, "No Android Manifest at: %1$s", resolvedPath); - return; - } - - // now get the target from the main project - ProjectProperties projectProp = ProjectProperties.load(resolvedPath, PropertyType.PROJECT); - if (projectProp == null) { - // legacy support for older file name. - projectProp = ProjectProperties.load(resolvedPath, PropertyType.LEGACY_DEFAULT); - if (projectProp == null) { - mLog.error(null, "No %1$s at: %2$s", PropertyType.PROJECT.getFilename(), - resolvedPath); - return; - } - } - - String targetHash = projectProp.getProperty(ProjectProperties.PROPERTY_TARGET); - if (targetHash == null) { - mLog.error(null, "%1$s in the main project has no target property.", - PropertyType.PROJECT.getFilename()); - return; - } - - IAndroidTarget target = sdkManager.getTargetFromHashString(targetHash); - if (target == null) { - mLog.error(null, "Main project target %1$s is not a valid target.", targetHash); - return; - } - - // update test-project does not support the --name parameter, therefore the project - // name should generally not be passed to updateProject(). - // However if build.xml does not exist then updateProject() will recreate it. In this - // case we will need the project name. - // To do this, we look for the parent project name and add "test" to it. - // If the main project does not have a project name (yet), then the default behavior - // will be used (look for activity and then folder name) - String projectName = null; - XPathFactory factory = XPathFactory.newInstance(); - XPath xpath = factory.newXPath(); - - File testBuildXml = new File(folderPath, SdkConstants.FN_BUILD_XML); - if (testBuildXml.isFile() == false) { - File mainBuildXml = new File(resolvedPath, SdkConstants.FN_BUILD_XML); - if (mainBuildXml.isFile()) { - try { - // get the name of the main project and add Test to it. - String mainProjectName = xpath.evaluate(XPATH_PROJECT_NAME, - new InputSource(new FileInputStream(mainBuildXml))); - projectName = mainProjectName + "Test"; - } catch (XPathExpressionException e) { - // it's ok, updateProject() will figure out a name automatically. - // We do log the error though as the build.xml file may be broken. - mLog.warning("Failed to parse %1$s.\n" + - "File may not be valid. Consider running 'android update project' on the main project.", - mainBuildXml.getPath()); - } catch (FileNotFoundException e) { - // should not happen since we check first. - } - } - } - - // now update the project as if it's a normal project - if (updateProject(folderPath, target, projectName, null /*libraryPath*/) == false) { - // error message has already been displayed. - return; - } - - // add the test project specific properties. - // At this point, we know build.prop has been renamed ant.prop - ProjectProperties antProps = ProjectProperties.load(folderPath, PropertyType.ANT); - ProjectPropertiesWorkingCopy antWorkingCopy; - if (antProps == null) { - antWorkingCopy = ProjectProperties.create(folderPath, PropertyType.ANT); - } else { - antWorkingCopy = antProps.makeWorkingCopy(); - } - - // set or replace the path to the main project - antWorkingCopy.setProperty(ProjectProperties.PROPERTY_TESTED_PROJECT, pathToMainProject); - try { - antWorkingCopy.save(); - println("Updated %1$s", PropertyType.ANT.getFilename()); - } catch (Exception e) { - mLog.error(e, "Failed to write %1$s file in '%2$s'", - PropertyType.ANT.getFilename(), - folderPath); - return; - } - } - - /** - * Checks whether the give folderPath is a valid project folder, and returns - * a {@link FileWrapper} to the required file. - *

This checks that the folder exists and contains an AndroidManifest.xml file in it. - *

Any error are output using {@link #mLog}. - * @param folderPath the folder to check - * @param requiredFilename the file name of the file that's required. - * @return a {@link FileWrapper} to the AndroidManifest.xml file, or null otherwise. - */ - private FileWrapper checkProjectFolder(String folderPath, String requiredFilename) { - // project folder must exist and be a directory, since this is an update - FolderWrapper projectFolder = new FolderWrapper(folderPath); - if (!projectFolder.isDirectory()) { - mLog.error(null, "Project folder '%1$s' is not a valid directory.", - projectFolder); - return null; - } - - // Check AndroidManifest.xml is present - FileWrapper requireFile = new FileWrapper(projectFolder, requiredFilename); - if (!requireFile.isFile()) { - mLog.error(null, - "%1$s is not a valid project (%2$s not found).", - folderPath, requiredFilename); - return null; - } - - return requireFile; - } - - /** - * Looks for a given regex in a file and returns the matcher if any line of the input file - * contains the requested regexp. - * - * @param file the file to search. - * @param regexp the regexp to search for. - * - * @return a Matcher or null if the regexp is not found. - */ - private Matcher checkFileContainsRegexp(File file, String regexp) { - Pattern p = Pattern.compile(regexp); - - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(file)); - String line; - - while ((line = in.readLine()) != null) { - Matcher m = p.matcher(line); - if (m.find()) { - return m; - } - } - - in.close(); - } catch (Exception e) { - // ignore - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - } - - return null; - } - - /** - * Extracts a "full" package & activity name from an AndroidManifest.xml. - *

- * The keywords dictionary is always filed the package name under the key {@link #PH_PACKAGE}. - * If an activity name can be found, it is filed under the key {@link #PH_ACTIVITY_ENTRY_NAME}. - * When no activity is found, this key is not created. - * - * @param manifestFile The AndroidManifest.xml file - * @param outKeywords Place where to put the out parameters: package and activity names. - * @return True if the package/activity was parsed and updated in the keyword dictionary. - */ - private boolean extractPackageFromManifest(File manifestFile, - Map outKeywords) { - try { - XPath xpath = AndroidXPathFactory.newXPath(); - - InputSource source = new InputSource(new FileReader(manifestFile)); - String packageName = xpath.evaluate("/manifest/@package", source); - - source = new InputSource(new FileReader(manifestFile)); - - // Select the "android:name" attribute of all nodes but only if they - // contain a sub-node with an "android:name" attribute which - // is 'android.intent.action.MAIN' and an with an - // "android:name" attribute which is 'android.intent.category.LAUNCHER' - String expression = String.format("/manifest/application/activity" + - "[intent-filter/action/@%1$s:name='android.intent.action.MAIN' and " + - "intent-filter/category/@%1$s:name='android.intent.category.LAUNCHER']" + - "/@%1$s:name", AndroidXPathFactory.DEFAULT_NS_PREFIX); - - NodeList activityNames = (NodeList) xpath.evaluate(expression, source, - XPathConstants.NODESET); - - // If we get here, both XPath expressions were valid so we're most likely dealing - // with an actual AndroidManifest.xml file. The nodes may not have the requested - // attributes though, if which case we should warn. - - if (packageName == null || packageName.isEmpty()) { - mLog.error(null, - "Missing in '%1$s'", - manifestFile.getName()); - return false; - } - - // Get the first activity that matched earlier. If there is no activity, - // activityName is set to an empty string and the generated "combined" name - // will be in the form "package." (with a dot at the end). - String activityName = ""; - if (activityNames.getLength() > 0) { - activityName = activityNames.item(0).getNodeValue(); - } - - if (mLevel == OutputLevel.VERBOSE && activityNames.getLength() > 1) { - println("WARNING: There is more than one activity defined in '%1$s'.\n" + - "Only the first one will be used. If this is not appropriate, you need\n" + - "to specify one of these values manually instead:", - manifestFile.getName()); - - for (int i = 0; i < activityNames.getLength(); i++) { - String name = activityNames.item(i).getNodeValue(); - name = combinePackageActivityNames(packageName, name); - println("- %1$s", name); - } - } - - if (activityName.isEmpty()) { - mLog.warning("Missing in '%2$s'.\n" + - "No activity will be generated.", - AndroidXPathFactory.DEFAULT_NS_PREFIX, manifestFile.getName()); - } else { - outKeywords.put(PH_ACTIVITY_ENTRY_NAME, activityName); - } - - outKeywords.put(PH_PACKAGE, packageName); - return true; - - } catch (IOException e) { - mLog.error(e, "Failed to read %1$s", manifestFile.getName()); - } catch (XPathExpressionException e) { - Throwable t = e.getCause(); - mLog.error(t == null ? e : t, - "Failed to parse %1$s", - manifestFile.getName()); - } - - return false; - } - - private String combinePackageActivityNames(String packageName, String activityName) { - // Activity Name can have 3 forms: - // - ".Name" means this is a class name in the given package name. - // The full FQCN is thus packageName + ".Name" - // - "Name" is an older variant of the former. Full FQCN is packageName + "." + "Name" - // - "com.blah.Name" is a full FQCN. Ignore packageName and use activityName as-is. - // To be valid, the package name should have at least two components. This is checked - // later during the creation of the build.xml file, so we just need to detect there's - // a dot but not at pos==0. - - int pos = activityName.indexOf('.'); - if (pos == 0) { - return packageName + activityName; - } else if (pos > 0) { - return activityName; - } else { - return packageName + "." + activityName; - } - } - - /** - * Installs a new file that is based on a template file provided by a given target. - * Each match of each key from the place-holder map in the template will be replaced with its - * corresponding value in the created file. - * - * @param templateName the name of to the template file - * @param destFile the path to the destination file, relative to the project - * @param placeholderMap a map of (place-holder, value) to create the file from the template. - * @param target the Target of the project that will be providing the template. - * @throws ProjectCreateException - */ - private void installTargetTemplate(String templateName, File destFile, - Map placeholderMap, IAndroidTarget target) - throws ProjectCreateException { - // query the target for its template directory - String templateFolder = target.getPath(IAndroidTarget.TEMPLATES); - final String sourcePath = templateFolder + File.separator + templateName; - - installFullPathTemplate(sourcePath, destFile, placeholderMap); - } - - /** - * Installs a new file from the gradle wrapper template. - * - * @param templateName the name of the template file - * @param projectFolder the path to the project folder - * @throws ProjectCreateException - */ - public void installGradleWrapperFile(String templateName, File projectFolder) - throws ProjectCreateException { - String templateFolder = mSdkFolder + File.separator + - SdkConstants.OS_SDK_TOOLS_TEMPLATES_GRADLE_WRAPPER_FOLDER; - - installBinaryFile(new File(templateFolder, templateName), - new File(projectFolder, templateName)); - } - - /** - * Installs a new file that is based on a template file provided by the tools folder. - * Each match of each key from the place-holder map in the template will be replaced with its - * corresponding value in the created file. - * - * @param templateName the name of to the template file - * @param destFile the path to the destination file, relative to the project - * @param placeholderMap a map of (place-holder, value) to create the file from the template. - * @throws ProjectCreateException - */ - public void installTemplate(String templateName, File destFile, - Map placeholderMap) - throws ProjectCreateException { - // query the target for its template directory - String templateFolder = mSdkFolder + File.separator + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER; - final String sourcePath = templateFolder + File.separator + templateName; - - installFullPathTemplate(sourcePath, destFile, placeholderMap); - } - - /** - * Installs a new file that is based on a template. - * Each match of each key from the place-holder map in the template will be replaced with its - * corresponding value in the created file. - * - * @param sourcePath the full path to the source template file - * @param destFile the destination file - * @param placeholderMap a map of (place-holder, value) to create the file from the template. - * @throws ProjectCreateException - */ - private void installFullPathTemplate(String sourcePath, File destFile, - Map placeholderMap) throws ProjectCreateException { - - boolean existed = destFile.exists(); - - try { - BufferedWriter out = new BufferedWriter(new FileWriter(destFile)); - BufferedReader in = new BufferedReader(new FileReader(sourcePath)); - String line; - - while ((line = in.readLine()) != null) { - if (placeholderMap != null) { - for (Map.Entry entry : placeholderMap.entrySet()) { - line = line.replace(entry.getKey(), entry.getValue()); - } - } - - out.write(line); - out.newLine(); - } - - out.close(); - in.close(); - } catch (Exception e) { - throw new ProjectCreateException(e, "Could not access %1$s: %2$s", - destFile, e.getMessage()); - } - - println("%1$s file %2$s", - existed ? "Updated" : "Added", - destFile); - } - - /** - * Installs the project icons. - * @param resourceFolder the resource folder - * @param target the target of the project. - * @return true if any icon was installed. - */ - private boolean installIcons(File resourceFolder, IAndroidTarget target) - throws ProjectCreateException { - // query the target for its template directory - String templateFolder = target.getPath(IAndroidTarget.TEMPLATES); - - boolean installedIcon = false; - - installedIcon |= installIcon(templateFolder, "ic_launcher_xhdpi.png", resourceFolder, - "drawable-xhdpi"); - installedIcon |= installIcon(templateFolder, "ic_launcher_hdpi.png", resourceFolder, - "drawable-hdpi"); - installedIcon |= installIcon(templateFolder, "ic_launcher_mdpi.png", resourceFolder, - "drawable-mdpi"); - installedIcon |= installIcon(templateFolder, "ic_launcher_ldpi.png", resourceFolder, - "drawable-ldpi"); - - return installedIcon; - } - - /** - * Installs an Icon in the project. - * @return true if the icon was installed. - */ - private boolean installIcon(String templateFolder, String iconName, File resourceFolder, - String folderName) throws ProjectCreateException { - File icon = new File(templateFolder, iconName); - if (icon.exists()) { - File drawable = createDirs(resourceFolder, folderName); - installBinaryFile(icon, new File(drawable, "ic_launcher.png")); - return true; - } - - return false; - } - - /** - * Installs a binary file - * @param source the source file to copy - * @param destination the destination file to write - * @throws ProjectCreateException - */ - private void installBinaryFile(File source, File destination) throws ProjectCreateException { - byte[] buffer = new byte[8192]; - - FileInputStream fis = null; - FileOutputStream fos = null; - try { - fis = new FileInputStream(source); - fos = new FileOutputStream(destination); - - int read; - while ((read = fis.read(buffer)) != -1) { - fos.write(buffer, 0, read); - } - - } catch (FileNotFoundException e) { - // shouldn't happen since we check before. - } catch (IOException e) { - throw new ProjectCreateException(e, "Failed to read binary file: %1$s", - source.getAbsolutePath()); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - // ignore - } - } - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - // ignore - } - } - } - - } - - /** - * Prints a message unless silence is enabled. - *

- * This is just a convenience wrapper around {@link ILogger#info(String, Object...)} from - * {@link #mLog} after testing if output level is {@link OutputLevel#VERBOSE}. - * - * @param format Format for String.format - * @param args Arguments for String.format - */ - private void println(String format, Object... args) { - if (mLevel != OutputLevel.SILENT) { - if (!format.endsWith("\n")) { - format += "\n"; - } - mLog.info(format, args); - } - } - - /** - * Creates a new folder, along with any parent folders that do not exists. - * - * @param parent the parent folder - * @param name the name of the directory to create. - * @throws ProjectCreateException - */ - private File createDirs(File parent, String name) throws ProjectCreateException { - final File newFolder = new File(parent, name); - boolean existedBefore = true; - - if (!newFolder.exists()) { - if (!newFolder.mkdirs()) { - throw new ProjectCreateException("Could not create directory: %1$s", newFolder); - } - existedBefore = false; - } - - if (newFolder.isDirectory()) { - if (!newFolder.canWrite()) { - throw new ProjectCreateException("Path is not writable: %1$s", newFolder); - } - } else { - throw new ProjectCreateException("Path is not a directory: %1$s", newFolder); - } - - if (!existedBefore) { - try { - println("Created directory %1$s", newFolder.getCanonicalPath()); - } catch (IOException e) { - throw new ProjectCreateException( - "Could not determine canonical path of created directory", e); - } - } - - return newFolder; - } - - /** - * Strips the string of beginning and trailing characters (multiple - * characters will be stripped, example stripString("..test...", '.') - * results in "test"; - * - * @param s the string to strip - * @param strip the character to strip from beginning and end - * @return the stripped string or the empty string if everything is stripped. - */ - private static String stripString(String s, char strip) { - final int sLen = s.length(); - int newStart = 0, newEnd = sLen - 1; - - while (newStart < sLen && s.charAt(newStart) == strip) { - newStart++; - } - while (newEnd >= 0 && s.charAt(newEnd) == strip) { - newEnd--; - } - - /* - * newEnd contains a char we want, and substring takes end as being - * exclusive - */ - newEnd++; - - if (newStart >= sLen || newEnd < 0) { - return ""; - } - - return s.substring(newStart, newEnd); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectProperties.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectProperties.java deleted file mode 100644 index 7c574694..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectProperties.java +++ /dev/null @@ -1,594 +0,0 @@ -/* - * 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.internal.project; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.io.FolderWrapper; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.io.StreamException; -import com.android.utils.ILogger; -import com.google.common.io.Closeables; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Class representing project properties for both ADT and Ant-based build. - *

The class is associated to a {@link PropertyType} that indicate which of the project - * property file is represented. - *

To load an existing file, use {@link #load(IAbstractFolder, PropertyType)}. - *

The class is meant to be always in sync (or at least not newer) than the file it represents. - * Once created, it can only be updated through {@link #reload()} - * - *

The make modification or make new file, use a {@link ProjectPropertiesWorkingCopy} instance, - * either through {@link #create(IAbstractFolder, PropertyType)} or through - * {@link #makeWorkingCopy()}. - * - */ -public class ProjectProperties implements IPropertySource { - protected static final Pattern PATTERN_PROP = Pattern.compile( - "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); - - /** The property name for the project target */ - public static final String PROPERTY_TARGET = "target"; - /** The property name for the renderscript build target */ - public static final String PROPERTY_RS_TARGET = "renderscript.target"; - /** The property name for the renderscript support mode */ - public static final String PROPERTY_RS_SUPPORT = "renderscript.support.mode"; - /** The version of the build tools to use to compile */ - public static final String PROPERTY_BUILD_TOOLS = "sdk.buildtools"; - - public static final String PROPERTY_LIBRARY = "android.library"; - public static final String PROPERTY_LIB_REF = "android.library.reference."; - private static final String PROPERTY_LIB_REF_REGEX = "android.library.reference.\\d+"; - - public static final String PROPERTY_PROGUARD_CONFIG = "proguard.config"; - public static final String PROPERTY_RULES_PATH = "layoutrules.jars"; - - public static final String PROPERTY_SDK = "sdk.dir"; - public static final String PROPERTY_NDK = "ndk.dir"; - // LEGACY - Kept so that we can actually remove it from local.properties. - private static final String PROPERTY_SDK_LEGACY = "sdk-location"; - - public static final String PROPERTY_SPLIT_BY_DENSITY = "split.density"; - public static final String PROPERTY_SPLIT_BY_ABI = "split.abi"; - public static final String PROPERTY_SPLIT_BY_LOCALE = "split.locale"; - - public static final String PROPERTY_TESTED_PROJECT = "tested.project.dir"; - - public static final String PROPERTY_BUILD_SOURCE_DIR = "source.dir"; - public static final String PROPERTY_BUILD_OUT_DIR = "out.dir"; - - public static final String PROPERTY_PACKAGE = "package"; - public static final String PROPERTY_VERSIONCODE = "versionCode"; - public static final String PROPERTY_PROJECTS = "projects"; - public static final String PROPERTY_KEY_STORE = "key.store"; - public static final String PROPERTY_KEY_ALIAS = "key.alias"; - - public enum PropertyType { - ANT(SdkConstants.FN_ANT_PROPERTIES, BUILD_HEADER, new String[] { - PROPERTY_BUILD_SOURCE_DIR, PROPERTY_BUILD_OUT_DIR - }, null), - PROJECT(SdkConstants.FN_PROJECT_PROPERTIES, DEFAULT_HEADER, new String[] { - PROPERTY_TARGET, PROPERTY_LIBRARY, PROPERTY_LIB_REF_REGEX, - PROPERTY_KEY_STORE, PROPERTY_KEY_ALIAS, PROPERTY_PROGUARD_CONFIG, - PROPERTY_RULES_PATH - }, null), - LOCAL(SdkConstants.FN_LOCAL_PROPERTIES, LOCAL_HEADER, new String[] { - PROPERTY_SDK - }, - new String[] { PROPERTY_SDK_LEGACY }), - @Deprecated - LEGACY_DEFAULT("default.properties", null, null, null), - @Deprecated - LEGACY_BUILD("build.properties", null, null, null); - - - private final String mFilename; - private final String mHeader; - private final Set mKnownProps; - private final Set mRemovedProps; - - /** - * Returns the PropertyTypes ordered the same way Ant order them. - */ - public static PropertyType[] getOrderedTypes() { - return new PropertyType[] { - PropertyType.LOCAL, PropertyType.ANT, PropertyType.PROJECT - }; - } - - PropertyType(String filename, String header, String[] validProps, String[] removedProps) { - mFilename = filename; - mHeader = header; - HashSet s = new HashSet(); - if (validProps != null) { - s.addAll(Arrays.asList(validProps)); - } - mKnownProps = Collections.unmodifiableSet(s); - - s = new HashSet(); - if (removedProps != null) { - s.addAll(Arrays.asList(removedProps)); - } - mRemovedProps = Collections.unmodifiableSet(s); - - } - - public String getFilename() { - return mFilename; - } - - public String getHeader() { - return mHeader; - } - - /** - * Returns whether a given property is known for the property type. - */ - public boolean isKnownProperty(String name) { - for (String propRegex : mKnownProps) { - if (propRegex.equals(name) || Pattern.matches(propRegex, name)) { - return true; - } - } - - return false; - } - - /** - * Returns whether a given property should be removed for the property type. - */ - public boolean isRemovedProperty(String name) { - for (String propRegex : mRemovedProps) { - if (propRegex.equals(name) || Pattern.matches(propRegex, name)) { - return true; - } - } - - return false; - } - } - - private static final String LOCAL_HEADER = -// 1-------10--------20--------30--------40--------50--------60--------70--------80 - "# This file is automatically generated by Android Tools.\n" + - "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" + - "#\n" + - "# This file must *NOT* be checked into Version Control Systems,\n" + - "# as it contains information specific to your local configuration.\n" + - "\n"; - - private static final String DEFAULT_HEADER = -// 1-------10--------20--------30--------40--------50--------60--------70--------80 - "# This file is automatically generated by Android Tools.\n" + - "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" + - "#\n" + - "# This file must be checked in Version Control Systems.\n" + - "#\n" + - "# To customize properties used by the Ant build system edit\n" + - "# \"ant.properties\", and override values to adapt the script to your\n" + - "# project structure.\n" + - "#\n" + - "# To enable ProGuard to shrink and obfuscate your code, uncomment this " - + "(available properties: sdk.dir, user.home):\n" + - // Note: always use / separators in the properties paths. Both Ant and - // our ExportHelper will convert them properly according to the platform. - "#" + PROPERTY_PROGUARD_CONFIG + "=${" + PROPERTY_SDK +"}/" - + SdkConstants.FD_TOOLS + '/' + SdkConstants.FD_PROGUARD + '/' - + SdkConstants.FN_ANDROID_PROGUARD_FILE + ':' - + SdkConstants.FN_PROJECT_PROGUARD_FILE +'\n' + - "\n"; - - private static final String BUILD_HEADER = -// 1-------10--------20--------30--------40--------50--------60--------70--------80 - "# This file is used to override default values used by the Ant build system.\n" + - "#\n" + - "# This file must be checked into Version Control Systems, as it is\n" + - "# integral to the build system of your project.\n" + - "\n" + - "# This file is only used by the Ant script.\n" + - "\n" + - "# You can use this to override default values such as\n" + - "# 'source.dir' for the location of your java source folder and\n" + - "# 'out.dir' for the location of your output folder.\n" + - "\n" + - "# You can also use it define how the release builds are signed by declaring\n" + - "# the following properties:\n" + - "# 'key.store' for the location of your keystore and\n" + - "# 'key.alias' for the name of the key to use.\n" + - "# The password will be asked during the build when you use the 'release' target.\n" + - "\n"; - - protected final IAbstractFolder mProjectFolder; - protected final Map mProperties; - protected final PropertyType mType; - - /** - * Loads a project properties file and return a {@link ProjectProperties} object - * containing the properties. - * - * @param projectFolderOsPath the project folder. - * @param type One the possible {@link PropertyType}s. - */ - public static ProjectProperties load(String projectFolderOsPath, PropertyType type) { - IAbstractFolder wrapper = new FolderWrapper(projectFolderOsPath); - return load(wrapper, type); - } - - /** - * Loads a project properties file and return a {@link ProjectProperties} object - * containing the properties. - * - * @param projectFolder the project folder. - * @param type One the possible {@link PropertyType}s. - */ - public static ProjectProperties load(IAbstractFolder projectFolder, PropertyType type) { - if (projectFolder.exists()) { - IAbstractFile propFile = projectFolder.getFile(type.mFilename); - if (propFile.exists()) { - Map map = parsePropertyFile(propFile, null /* log */); - if (map != null) { - return new ProjectProperties(projectFolder, map, type); - } - } - } - return null; - } - - /** - * Deletes a project properties file. - * - * @param projectFolder the project folder. - * @param type One the possible {@link PropertyType}s. - * @return true if success. - */ - public static boolean delete(IAbstractFolder projectFolder, PropertyType type) { - if (projectFolder.exists()) { - IAbstractFile propFile = projectFolder.getFile(type.mFilename); - if (propFile.exists()) { - return propFile.delete(); - } - } - - return false; - } - - /** - * Deletes a project properties file. - * - * @param projectFolderOsPath the project folder. - * @param type One the possible {@link PropertyType}s. - * @return true if success. - */ - public static boolean delete(String projectFolderOsPath, PropertyType type) { - IAbstractFolder wrapper = new FolderWrapper(projectFolderOsPath); - return delete(wrapper, type); - } - - - /** - * Creates a new project properties object, with no properties. - *

The file is not created until {@link ProjectPropertiesWorkingCopy#save()} is called. - * @param projectFolderOsPath the project folder. - * @param type the type of property file to create - * - * @see #createEmpty(String, PropertyType) - */ - public static ProjectPropertiesWorkingCopy create(@NonNull String projectFolderOsPath, - @NonNull PropertyType type) { - // create and return a ProjectProperties with an empty map. - IAbstractFolder folder = new FolderWrapper(projectFolderOsPath); - return create(folder, type); - } - - /** - * Creates a new project properties object, with no properties. - *

The file is not created until {@link ProjectPropertiesWorkingCopy#save()} is called. - * @param projectFolder the project folder. - * @param type the type of property file to create - * - * @see #createEmpty(IAbstractFolder, PropertyType) - */ - public static ProjectPropertiesWorkingCopy create(@NonNull IAbstractFolder projectFolder, - @NonNull PropertyType type) { - // create and return a ProjectProperties with an empty map. - return new ProjectPropertiesWorkingCopy(projectFolder, new HashMap(), type); - } - - /** - * Creates a new project properties object, with no properties. - *

Nothing can be added to it, unless a {@link ProjectPropertiesWorkingCopy} is created - * first with {@link #makeWorkingCopy()}. - * @param projectFolderOsPath the project folder. - * @param type the type of property file to create - * - * @see #create(String, PropertyType) - */ - public static ProjectProperties createEmpty(@NonNull String projectFolderOsPath, - @NonNull PropertyType type) { - // create and return a ProjectProperties with an empty map. - IAbstractFolder folder = new FolderWrapper(projectFolderOsPath); - return createEmpty(folder, type); - } - - /** - * Creates a new project properties object, with no properties. - *

Nothing can be added to it, unless a {@link ProjectPropertiesWorkingCopy} is created - * first with {@link #makeWorkingCopy()}. - * @param projectFolder the project folder. - * @param type the type of property file to create - * - * @see #create(IAbstractFolder, PropertyType) - */ - public static ProjectProperties createEmpty(@NonNull IAbstractFolder projectFolder, - @NonNull PropertyType type) { - // create and return a ProjectProperties with an empty map. - return new ProjectProperties(projectFolder, new HashMap(), type); - } - - /** - * Returns the location of this property file. - */ - public IAbstractFile getFile() { - return mProjectFolder.getFile(mType.mFilename); - } - - /** - * Creates and returns a copy of the current properties as a - * {@link ProjectPropertiesWorkingCopy} that can be modified and saved. - * @return a new instance of {@link ProjectPropertiesWorkingCopy} - */ - public ProjectPropertiesWorkingCopy makeWorkingCopy() { - return makeWorkingCopy(mType); - } - - /** - * Creates and returns a copy of the current properties as a - * {@link ProjectPropertiesWorkingCopy} that can be modified and saved. This also allows - * converting to a new type, by specifying a different {@link PropertyType}. - * - * @param type the {@link PropertyType} of the prop file to save. - * - * @return a new instance of {@link ProjectPropertiesWorkingCopy} - */ - public ProjectPropertiesWorkingCopy makeWorkingCopy(PropertyType type) { - // copy the current properties in a new map - Map propList = new HashMap(mProperties); - - return new ProjectPropertiesWorkingCopy(mProjectFolder, propList, type); - } - - /** - * Returns the type of the property file. - * - * @see PropertyType - */ - public PropertyType getType() { - return mType; - } - - /** - * 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. - */ - @Override - public synchronized String getProperty(String name) { - return mProperties.get(name); - } - - /** - * Returns a set of the property keys. Unlike {@link Map#keySet()} this is not a view of the - * map keys. Modifying the returned {@link Set} will not impact the underlying {@link Map}. - */ - public synchronized Set keySet() { - return new HashSet(mProperties.keySet()); - } - - /** - * Reloads the properties from the underlying file. - */ - public synchronized void reload() { - if (mProjectFolder.exists()) { - IAbstractFile propFile = mProjectFolder.getFile(mType.mFilename); - if (propFile.exists()) { - Map map = parsePropertyFile(propFile, null /* log */); - if (map != null) { - mProperties.clear(); - mProperties.putAll(map); - } - } - } - } - - /** - * Parses a property file (using UTF-8 encoding) and returns a map of the content. - *

- * If the file is not present, null is returned with no error messages sent to the log. - *

- * IMPORTANT: This method is now unfortunately used in multiple places to parse random - * property files. This is NOT a safe practice since there is no corresponding method - * to write property files unless you use {@link ProjectPropertiesWorkingCopy#save()}. - * Code that writes INI or properties without at least using {@link #escape(String)} will - * certainly not load back correct data.
- * Unless there's a strong legacy need to support existing files, new callers should - * probably just use Java's {@link Properties} which has well defined semantics. - * It's also a mistake to write/read property files using this code and expect it to - * work with Java's {@link Properties} or external tools (e.g. ant) since there can be - * differences in escaping and in character encoding. - * - * @param propFile the property file to parse - * @param log the ILogger object receiving warning/error from the parsing. - * @return the map of (key,value) pairs, or null if the parsing failed. - */ - public static Map parsePropertyFile( - @NonNull IAbstractFile propFile, - @Nullable ILogger log) { - InputStream is = null; - try { - is = propFile.getContents(); - return parsePropertyStream(is, - propFile.getOsLocation(), - log); - } catch (StreamException e) { - if (log != null) { - log.warning("Error parsing '%1$s': %2$s.", - propFile.getOsLocation(), - e.getMessage()); - } - } finally { - try { - Closeables.close(is, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - } - - - return null; - } - - /** - * Parses a property file (using UTF-8 encoding) and returns a map of the content. - *

- * Always closes the given input stream on exit. - *

- * IMPORTANT: This method is now unfortunately used in multiple places to parse random - * property files. This is NOT a safe practice since there is no corresponding method - * to write property files unless you use {@link ProjectPropertiesWorkingCopy#save()}. - * Code that writes INI or properties without at least using {@link #escape(String)} will - * certainly not load back correct data.
- * Unless there's a strong legacy need to support existing files, new callers should - * probably just use Java's {@link Properties} which has well defined semantics. - * It's also a mistake to write/read property files using this code and expect it to - * work with Java's {@link Properties} or external tools (e.g. ant) since there can be - * differences in escaping and in character encoding. - * - * @param propStream the input stream of the property file to parse. - * @param propPath the file path, for display purposed in case of error. - * @param log the ILogger object receiving warning/error from the parsing. - * @return the map of (key,value) pairs, or null if the parsing failed. - */ - public static Map parsePropertyStream( - @NonNull InputStream propStream, - @NonNull String propPath, - @Nullable ILogger log) { - BufferedReader reader = null; - try { - //noinspection IOResourceOpenedButNotSafelyClosed - reader = new BufferedReader( - new InputStreamReader(propStream, SdkConstants.INI_CHARSET)); - - String line = null; - Map map = new HashMap(); - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (!line.isEmpty() && line.charAt(0) != '#') { - - Matcher m = PATTERN_PROP.matcher(line); - if (m.matches()) { - map.put(m.group(1), unescape(m.group(2))); - } else { - if (log != null) { - log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax", - propPath, - 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.", - propPath, - e.getMessage()); - } - } finally { - try { - Closeables.close(reader, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - try { - Closeables.close(propStream, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - } - - return null; - } - - /** - * Private constructor. - *

- * Use {@link #load(String, PropertyType)} or {@link #create(String, PropertyType)} - * to instantiate. - */ - protected ProjectProperties( - @NonNull IAbstractFolder projectFolder, - @NonNull Map map, - @NonNull PropertyType type) { - mProjectFolder = projectFolder; - mProperties = map; - mType = type; - } - - private static String unescape(String value) { - return value.replaceAll("\\\\\\\\", "\\\\"); - } - - protected static String escape(String value) { - return value.replaceAll("\\\\", "\\\\\\\\"); - } - - @Override - public void debugPrint() { - System.out.println("DEBUG PROJECTPROPERTIES: " + mProjectFolder); - System.out.println("type: " + mType); - for (Entry entry : mProperties.entrySet()) { - System.out.println(entry.getKey() + " -> " + entry.getValue()); - } - System.out.println("<<< DEBUG PROJECTPROPERTIES"); - - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java deleted file mode 100644 index 4fac8f9d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.project; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.io.StreamException; -import com.google.common.io.Closeables; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.regex.Matcher; - -/** - * A modifiable and savable copy of a {@link ProjectProperties}. - *

This copy gives access to modification method such as {@link #setProperty(String, String)} - * and {@link #removeProperty(String)}. - * - * To get access to an instance, use {@link ProjectProperties#makeWorkingCopy()} or - * {@link ProjectProperties#create(IAbstractFolder, PropertyType)}. - */ -public class ProjectPropertiesWorkingCopy extends ProjectProperties { - - private static final Map COMMENT_MAP = new HashMap(); - static { -// 1-------10--------20--------30--------40--------50--------60--------70--------80 - COMMENT_MAP.put(PROPERTY_TARGET, - "# Project target.\n"); - COMMENT_MAP.put(PROPERTY_SPLIT_BY_DENSITY, - "# Indicates whether an apk should be generated for each density.\n"); - COMMENT_MAP.put(PROPERTY_SDK, - "# location of the SDK. This is only used by Ant\n" + - "# For customization when using a Version Control System, please read the\n" + - "# header note.\n"); - COMMENT_MAP.put(PROPERTY_PACKAGE, - "# Package of the application being exported\n"); - COMMENT_MAP.put(PROPERTY_VERSIONCODE, - "# Major version code\n"); - COMMENT_MAP.put(PROPERTY_PROJECTS, - "# List of the Android projects being used for the export.\n" + - "# The list is made of paths that are relative to this project,\n" + - "# using forward-slash (/) as separator, and are separated by colons (:).\n"); - } - - - /** - * 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 synchronized void setProperty(String name, String value) { - mProperties.put(name, value); - } - - /** - * Removes a property and returns its previous value (or null if the property did not exist). - * @param name the name of the property to remove. - */ - public synchronized String removeProperty(String name) { - return mProperties.remove(name); - } - - /** - * Merges all properties from the given file into the current properties. - *

- * This emulates the Ant behavior: existing properties are not overridden. - * Only new undefined properties become defined. - *

- * Typical usage: - *

    - *
  • Create a ProjectProperties with {@code PropertyType#ANT} - *
  • Merge in values using {@code PropertyType#PROJECT} - *
  • The result is that this contains all the properties from default plus those - * overridden by the build.properties file. - *
- * - * @param type One the possible {@link ProjectProperties.PropertyType}s. - * @return this object, for chaining. - */ - public synchronized ProjectPropertiesWorkingCopy merge(PropertyType type) { - if (mProjectFolder.exists() && mType != type) { - IAbstractFile propFile = mProjectFolder.getFile(type.getFilename()); - if (propFile.exists()) { - Map map = parsePropertyFile(propFile, null /* log */); - if (map != null) { - for (Entry entry : map.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (!mProperties.containsKey(key) && value != null) { - mProperties.put(key, value); - } - } - } - } - } - return this; - } - - - /** - * Saves the property file, using UTF-8 encoding. - * @throws IOException - * @throws StreamException - */ - public synchronized void save() throws IOException, StreamException { - IAbstractFile toSave = mProjectFolder.getFile(mType.getFilename()); - - // write the whole file in a byte array before dumping it in the file. This - // This is so that if the file already existing - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(baos, SdkConstants.INI_CHARSET); - - if (toSave.exists()) { - InputStream contentStream = toSave.getContents(); - InputStreamReader isr = null; - BufferedReader reader = null; - - try { - contentStream = toSave.getContents(); - //noinspection IOResourceOpenedButNotSafelyClosed - isr = new InputStreamReader(contentStream, SdkConstants.INI_CHARSET); - //noinspection IOResourceOpenedButNotSafelyClosed - reader = new BufferedReader(isr); - - // since we're reading the existing file and replacing values with new ones, or skipping - // removed values, we need to record what properties have been visited, so that - // we can figure later what new properties need to be added at the end of the file. - Set visitedProps = new HashSet(); - - String line = null; - while ((line = reader.readLine()) != null) { - // check if this is a line containing a property. - if (!line.isEmpty() && line.charAt(0) != '#') { - - Matcher m = PATTERN_PROP.matcher(line); - if (m.matches()) { - String key = m.group(1); - String value = m.group(2); - - // record the prop - visitedProps.add(key); - - // check if this property must be removed. - if (mType.isRemovedProperty(key)) { - value = null; - } else if (mProperties.containsKey(key)) { // if the property still exists. - // put the new value. - value = mProperties.get(key); - } else { - // property doesn't exist. Check if it's a known property. - // if it's a known one, we'll remove it, otherwise, leave it untouched. - if (mType.isKnownProperty(key)) { - value = null; - } - } - - // if the value is still valid, write it down. - if (value != null) { - writeValue(writer, key, value, false /*addComment*/); - } - } else { - // the line was wrong, let's just ignore it so that it's removed from the - // file. - } - } else { - // non-property line: just write the line in the output as-is. - writer.append(line).append('\n'); - } - } - - // now add the new properties. - for (Entry entry : mProperties.entrySet()) { - if (!visitedProps.contains(entry.getKey())) { - String value = entry.getValue(); - if (value != null) { - writeValue(writer, entry.getKey(), value, true /*addComment*/); - } - } - } - } finally { - try { - Closeables.close(reader, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - try { - Closeables.close(isr, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - try { - Closeables.close(contentStream, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - } - - } else { - // new file, just write it all - - // write the header (can be null, for example for PropertyType.LEGACY_BUILD) - if (mType.getHeader() != null) { - writer.write(mType.getHeader()); - } - - // write the properties. - for (Entry entry : mProperties.entrySet()) { - String value = entry.getValue(); - if (value != null) { - writeValue(writer, entry.getKey(), value, true /*addComment*/); - } - } - } - - writer.flush(); - - // now put the content in the file. - OutputStream filestream = toSave.getOutputStream(); - filestream.write(baos.toByteArray()); - filestream.flush(); - filestream.close(); - } - - private void writeValue(OutputStreamWriter writer, String key, String value, - boolean addComment) throws IOException { - if (addComment) { - String comment = COMMENT_MAP.get(key); - if (comment != null) { - writer.write(comment); - } - } - - writer.write(String.format("%s=%s\n", key, escape(value))); - } - - /** - * Private constructor. - *

- * Use {@link #load(String, PropertyType)} or {@link #create(String, PropertyType)} - * to instantiate. - */ - ProjectPropertiesWorkingCopy(IAbstractFolder projectFolder, Map map, - PropertyType type) { - super(projectFolder, map, type); - } - - @NonNull - public ProjectProperties makeReadOnlyCopy() { - // copy the current properties in a new map - Map propList = new HashMap(mProperties); - - return new ProjectProperties(mProjectFolder, propList, mType); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AdbWrapper.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AdbWrapper.java deleted file mode 100644 index ae256eb3..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AdbWrapper.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository; - -import com.android.SdkConstants; - -import java.io.File; -import java.io.IOException; - -/** - * A lightweight wrapper to start & stop ADB. - * This is specific to the SDK Manager install process. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class AdbWrapper { - - /* - * Note: we could bring ddmlib in SdkManager for that purpose, however this allows us to - * specialize the start/stop methods to our needs (e.g. a task monitor, etc.) - */ - - private final String mAdbOsLocation; - private final ITaskMonitor mMonitor; - - /** - * Creates a new lightweight ADB wrapper. - * - * @param osSdkPath The root OS path of the SDK. Cannot be null. - * @param monitor A logger object. Cannot be null. - */ - public AdbWrapper(String osSdkPath, ITaskMonitor monitor) { - mMonitor = monitor; - - if (!osSdkPath.endsWith(File.separator)) { - osSdkPath += File.separator; - } - mAdbOsLocation = osSdkPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER - + SdkConstants.FN_ADB; - } - - private void display(String format, Object...args) { - mMonitor.log(format, args); - } - - private void displayError(String format, Object...args) { - mMonitor.logError(format, args); - } - - /** - * Starts the adb host side server. - * @return true if success - */ - public synchronized boolean startAdb() { - if (mAdbOsLocation == null) { - displayError("Error: missing path to ADB."); //$NON-NLS-1$ - return false; - } - - Process proc; - int status = -1; - - try { - ProcessBuilder processBuilder = new ProcessBuilder( - mAdbOsLocation, - "start-server"); //$NON-NLS-1$ - proc = processBuilder.start(); - status = proc.waitFor(); - - // Implementation note: normally on Windows we need to capture stderr/stdout - // to make sure the process isn't blocked if it's output isn't read. However - // in this case this happens to hang when reading stdout with no proper way - // to properly close the streams. On the other hand the output from start - // server is rather short and not very interesting so we just drop it. - - } catch (IOException ioe) { - displayError("Unable to run 'adb': %1$s.", ioe.getMessage()); //$NON-NLS-1$ - // we'll return false; - } catch (InterruptedException ie) { - displayError("Unable to run 'adb': %1$s.", ie.getMessage()); //$NON-NLS-1$ - // we'll return false; - } - - if (status != 0) { - displayError(String.format( - "Starting ADB server failed (code %d).", //$NON-NLS-1$ - status)); - return false; - } - - display("Starting ADB server succeeded."); //$NON-NLS-1$ - - return true; - } - - /** - * Stops the adb host side server. - * @return true if success - */ - public synchronized boolean stopAdb() { - if (mAdbOsLocation == null) { - displayError("Error: missing path to ADB."); //$NON-NLS-1$ - return false; - } - - Process proc; - int status = -1; - - try { - String[] command = new String[2]; - command[0] = mAdbOsLocation; - command[1] = "kill-server"; //$NON-NLS-1$ - proc = Runtime.getRuntime().exec(command); - status = proc.waitFor(); - - // See comment in startAdb about not needing/wanting to capture stderr/stdout. - } - catch (IOException ioe) { - // we'll return false; - } - catch (InterruptedException ie) { - // we'll return false; - } - - // adb kill-server returns: - // 0 if adb was running and was correctly killed. - // 1 if adb wasn't running and thus wasn't killed. - // This error case is not worth reporting. - - if (status != 0 && status != 1) { - displayError(String.format( - "Stopping ADB server failed (code %d).", //$NON-NLS-1$ - status)); - return false; - } - - display("Stopping ADB server succeeded."); //$NON-NLS-1$ - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AddonsListFetcher.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AddonsListFetcher.java deleted file mode 100644 index 816c7f0e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/AddonsListFetcher.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository; - -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.io.NonClosingInputStream; -import com.android.io.NonClosingInputStream.CloseBehavior; -import com.android.sdklib.repository.SdkAddonsListConstants; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.net.ssl.SSLKeyException; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; - -/** - * Fetches and loads an sdk-addons-list XML. - *

- * Such an XML contains a simple list of add-ons site that are to be loaded by default by the - * SDK Manager.
- * The XML must conform to the sdk-addons-list-N.xsd.
- * Constants used in the XML are defined in {@link SdkAddonsListConstants}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class AddonsListFetcher { - - public enum SiteType { - ADDON_SITE, - SYS_IMG_SITE - } - - /** - * An immutable structure representing an add-on site. - */ - public static class Site { - private final String mUrl; - private final String mUiName; - private final SiteType mType; - - private Site(String url, String uiName, SiteType type) { - mType = type; - mUrl = url.trim(); - mUiName = uiName; - } - - public String getUrl() { - return mUrl; - } - - public String getUiName() { - return mUiName; - } - - public SiteType getType() { - return mType; - } - - /** Returns a debug string representation of this object. Not for user display. */ - @Override - public String toString() { - return String.format("<%1$s URL='%2$s' Name='%3$s'>", //$NON-NLS-1$ - mType, mUrl, mUiName); - } - } - - /** - * Fetches the addons list from the given URL. - * - * @param url The URL of an XML file resource that conforms to the latest sdk-addons-list-N.xsd. - * For the default operation, use {@link SdkAddonsListConstants#URL_ADDON_LIST}. - * Cannot be null. - * @param cache The {@link DownloadCache} instance to use. Cannot be null. - * @param monitor A monitor to report errors. Cannot be null. - * @return An array of {@link Site} on success (possibly empty), or null on error. - */ - public Site[] fetch(String url, DownloadCache cache, ITaskMonitor monitor) { - - url = url == null ? "" : url.trim(); - - monitor.setProgressMax(6); - monitor.setDescription("Fetching %1$s", url); - monitor.incProgress(1); - - Exception[] exception = new Exception[] { null }; - Boolean[] validatorFound = new Boolean[] { Boolean.FALSE }; - String[] validationError = new String[] { null }; - Document validatedDoc = null; - String validatedUri = null; - - String[] defaultNames = new String[SdkAddonsListConstants.NS_LATEST_VERSION]; - for (int version = SdkAddonsListConstants.NS_LATEST_VERSION, i = 0; - version >= 1; - version--, i++) { - defaultNames[i] = SdkAddonsListConstants.getDefaultName(version); - } - - InputStream xml = fetchXmlUrl(url, cache, monitor.createSubMonitor(1), exception); - if (xml != null) { - int version = getXmlSchemaVersion(xml); - if (version == 0) { - closeStream(xml); - xml = null; - } - } - - String baseUrl = url; - if (!baseUrl.endsWith("/")) { //$NON-NLS-1$ - int pos = baseUrl.lastIndexOf('/'); - if (pos > 0) { - baseUrl = baseUrl.substring(0, pos + 1); - } - } - - // If we can't find the latest version, try earlier schema versions. - if (xml == null && defaultNames.length > 0) { - ITaskMonitor subMonitor = monitor.createSubMonitor(1); - subMonitor.setProgressMax(defaultNames.length); - - for (String name : defaultNames) { - String newUrl = baseUrl + name; - if (newUrl.equals(url)) { - continue; - } - xml = fetchXmlUrl(newUrl, cache, subMonitor.createSubMonitor(1), exception); - if (xml != null) { - int version = getXmlSchemaVersion(xml); - if (version == 0) { - closeStream(xml); - xml = null; - } else { - url = newUrl; - subMonitor.incProgress( - subMonitor.getProgressMax() - subMonitor.getProgress()); - break; - } - } - } - } else { - monitor.incProgress(1); - } - - if (xml != null) { - monitor.setDescription("Validate XML"); - - // Explore the XML to find the potential XML schema version - int version = getXmlSchemaVersion(xml); - - if (version >= 1 && version <= SdkAddonsListConstants.NS_LATEST_VERSION) { - // This should be a version we can handle. Try to validate it - // and report any error as invalid XML syntax, - - String uri = validateXml(xml, url, version, validationError, validatorFound); - if (uri != null) { - // Validation was successful - validatedDoc = getDocument(xml, monitor); - validatedUri = uri; - - } - } else if (version > SdkAddonsListConstants.NS_LATEST_VERSION) { - // The schema used is more recent than what is supported by this tool. - // We don't have an upgrade-path support yet, so simply ignore the document. - closeStream(xml); - return null; - } - } - - // If any exception was handled during the URL fetch, display it now. - if (exception[0] != null) { - String reason = null; - if (exception[0] instanceof FileNotFoundException) { - // FNF has no useful getMessage, so we need to special handle it. - reason = "File not found"; - } else if (exception[0] instanceof UnknownHostException && - exception[0].getMessage() != null) { - // This has no useful getMessage yet could really use one - reason = String.format("Unknown Host %1$s", exception[0].getMessage()); - } else if (exception[0] instanceof SSLKeyException) { - // That's a common error and we have a pref for it. - reason = "HTTPS SSL error. You might want to force download through HTTP in the settings."; - } else if (exception[0].getMessage() != null) { - reason = exception[0].getMessage(); - } else { - // We don't know what's wrong. Let's give the exception class at least. - reason = String.format("Unknown (%1$s)", exception[0].getClass().getName()); - } - - monitor.logError("Failed to fetch URL %1$s, reason: %2$s", url, reason); - } - - if (validationError[0] != null) { - monitor.logError("%s", validationError[0]); //$NON-NLS-1$ - } - - // Stop here if we failed to validate the XML. We don't want to load it. - if (validatedDoc == null) { - closeStream(xml); - return null; - } - - monitor.incProgress(1); - - Site[] result = null; - - if (xml != null) { - monitor.setDescription("Parse XML"); - monitor.incProgress(1); - result = parseAddonsList(validatedDoc, validatedUri, baseUrl, monitor); - } - - // done - monitor.incProgress(1); - - closeStream(xml); - return result; - } - - /** - * Fetches the document at the given URL and returns it as a stream. Returns - * null if anything wrong happens. - * - * @param urlString The URL to load, as a string. - * @param monitor {@link ITaskMonitor} related to this URL. - * @param outException If non null, where to store any exception that - * happens during the fetch. - * @see UrlOpener UrlOpener, which handles all URL logic. - */ - private InputStream fetchXmlUrl(String urlString, - DownloadCache cache, - ITaskMonitor monitor, - Exception[] outException) { - try { - InputStream xml = cache.openCachedUrl(urlString, monitor); - if (xml != null) { - xml.mark(500000); - xml = new NonClosingInputStream(xml); - ((NonClosingInputStream) xml).setCloseBehavior(CloseBehavior.RESET); - } - return xml; - } catch (Exception e) { - if (outException != null) { - outException[0] = e; - } - } - - return null; - } - - /** - * Closes the stream, ignore any exception from InputStream.close(). - * If the stream is a NonClosingInputStream, sets it to CloseBehavior.CLOSE first. - */ - private void closeStream(InputStream is) { - if (is != null) { - if (is instanceof NonClosingInputStream) { - ((NonClosingInputStream) is).setCloseBehavior(CloseBehavior.CLOSE); - } - try { - is.close(); - } catch (IOException ignore) {} - } - } - - /** - * Manually parses the root element of the XML to extract the schema version - * at the end of the xmlns:sdk="http://schemas.android.com/sdk/android/addons-list/$N" - * declaration. - * - * @return 1..{@link SdkAddonsListConstants#NS_LATEST_VERSION} for a valid schema version - * or 0 if no schema could be found. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected int getXmlSchemaVersion(InputStream xml) { - if (xml == null) { - return 0; - } - - // Get an XML document - Document doc = null; - try { - assert xml.markSupported(); - xml.reset(); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(false); - factory.setValidating(false); - - // Parse the old document using a non namespace aware builder - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - - // We don't want the default handler which prints errors to stderr. - builder.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException e) throws SAXException { - // pass - } - @Override - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - @Override - public void error(SAXParseException e) throws SAXException { - throw e; - } - }); - - doc = builder.parse(xml); - - // Prepare a new document using a namespace aware builder - factory.setNamespaceAware(true); - builder = factory.newDocumentBuilder(); - - } catch (Exception e) { - // Failed to reset XML stream - // Failed to get builder factor - // Failed to create XML document builder - // Failed to parse XML document - // Failed to read XML document - //--For debug--System.err.println("getXmlSchemaVersion exception: " + e.toString()); - } - - if (doc == null) { - return 0; - } - - // Check the root element is an XML with at least the following properties: - // - // - // Note that we don't have namespace support enabled, we just do it manually. - - Pattern nsPattern = Pattern.compile(SdkAddonsListConstants.NS_PATTERN); - - String prefix = null; - for (Node child = doc.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - prefix = null; - String name = child.getNodeName(); - int pos = name.indexOf(':'); - if (pos > 0 && pos < name.length() - 1) { - prefix = name.substring(0, pos); - name = name.substring(pos + 1); - } - if (SdkAddonsListConstants.NODE_SDK_ADDONS_LIST.equals(name)) { - NamedNodeMap attrs = child.getAttributes(); - String xmlns = "xmlns"; //$NON-NLS-1$ - if (prefix != null) { - xmlns += ":" + prefix; //$NON-NLS-1$ - } - Node attr = attrs.getNamedItem(xmlns); - if (attr != null) { - String uri = attr.getNodeValue(); - if (uri != null) { - Matcher m = nsPattern.matcher(uri); - if (m.matches()) { - String version = m.group(1); - try { - return Integer.parseInt(version); - } catch (NumberFormatException e) { - return 0; - } - } - } - } - } - } - } - - return 0; - } - - /** - * Validates this XML against one of the requested SDK Repository schemas. - * If the XML was correctly validated, returns the schema that worked. - * If it doesn't validate, returns null and stores the error in outError[0]. - * If we can't find a validator, returns null and set validatorFound[0] to false. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected String validateXml(InputStream xml, String url, int version, - String[] outError, Boolean[] validatorFound) { - - if (xml == null) { - return null; - } - - try { - Validator validator = getValidator(version); - - if (validator == null) { - validatorFound[0] = Boolean.FALSE; - outError[0] = String.format( - "XML verification failed for %1$s.\nNo suitable XML Schema Validator could be found in your Java environment. Please consider updating your version of Java.", - url); - return null; - } - - validatorFound[0] = Boolean.TRUE; - - // Reset the stream if it supports that operation. - assert xml.markSupported(); - xml.reset(); - - // Validation throws a bunch of possible Exceptions on failure. - validator.validate(new StreamSource(xml)); - return SdkAddonsListConstants.getSchemaUri(version); - - } catch (SAXParseException e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nLine %2$d:%3$d, Error: %4$s", - url, - e.getLineNumber(), - e.getColumnNumber(), - e.toString()); - - } catch (Exception e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nError: %2$s", - url, - e.toString()); - } - return null; - } - - /** - * Helper method that returns a validator for our XSD, or null if the current Java - * implementation can't process XSD schemas. - * - * @param version The version of the XML Schema. - * See {@link SdkAddonsListConstants#getXsdStream(int)} - */ - private Validator getValidator(int version) throws SAXException { - InputStream xsdStream = SdkAddonsListConstants.getXsdStream(version); - SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - - if (factory == null) { - return null; - } - - // This may throw a SAX Exception if the schema itself is not a valid XSD - Schema schema = factory.newSchema(new StreamSource(xsdStream)); - - Validator validator = schema == null ? null : schema.newValidator(); - - return validator; - } - - /** - * Takes an XML document as a string as parameter and returns a DOM for it. - * - * On error, returns null and prints a (hopefully) useful message on the monitor. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Document getDocument(InputStream xml, ITaskMonitor monitor) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(true); - factory.setNamespaceAware(true); - - DocumentBuilder builder = factory.newDocumentBuilder(); - assert xml.markSupported(); - xml.reset(); - Document doc = builder.parse(new InputSource(xml)); - - return doc; - } catch (ParserConfigurationException e) { - monitor.logError("Failed to create XML document builder"); - - } catch (SAXException e) { - monitor.logError("Failed to parse XML document"); - - } catch (IOException e) { - monitor.logError("Failed to read XML document"); - } - - return null; - } - - /** - * Parse all sites defined in the Addons list XML and returns an array of sites. - * - * @param doc The XML DOM to parse. - * @param nsUri The addons-list schema URI of the document. - * @param baseUrl The base URL of the caller (e.g. where addons-list-N.xml was fetched from.) - * @param monitor A non-null monitor to print to. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Site[] parseAddonsList( - Document doc, - String nsUri, - String baseUrl, - ITaskMonitor monitor) { - - String testBaseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (testBaseUrl != null) { - if (testBaseUrl.length() <= 0 || !testBaseUrl.endsWith("/")) { //$NON-NLS-1$ - testBaseUrl = null; - } - } - - Node root = getFirstChild(doc, nsUri, SdkAddonsListConstants.NODE_SDK_ADDONS_LIST); - if (root != null) { - ArrayList sites = new ArrayList(); - - for (Node child = root.getFirstChild(); - child != null; - child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI())) { - - String elementName = child.getLocalName(); - SiteType type = null; - - if (SdkAddonsListConstants.NODE_SYS_IMG_SITE.equals(elementName)) { - type = SiteType.SYS_IMG_SITE; - - } else if (SdkAddonsListConstants.NODE_ADDON_SITE.equals(elementName)) { - type = SiteType.ADDON_SITE; - } - - // Not an addon-site nor a sys-img-site, don't process this. - if (type == null) { - continue; - } - - Node url = getFirstChild(child, nsUri, SdkAddonsListConstants.NODE_URL); - Node name = getFirstChild(child, nsUri, SdkAddonsListConstants.NODE_NAME); - - if (name != null && url != null) { - String strUrl = url.getTextContent().trim(); - String strName = name.getTextContent().trim(); - - if (testBaseUrl != null && - strUrl.startsWith(SdkRepoConstants.URL_GOOGLE_SDK_SITE)) { - strUrl = testBaseUrl + - strUrl.substring(SdkRepoConstants.URL_GOOGLE_SDK_SITE.length()); - } else if (!strUrl.startsWith("http://") && //$NON-NLS-1$ - !strUrl.startsWith("https://")) { //$NON-NLS-1$ - // This looks like a relative URL, add the fetcher's base URL to it. - strUrl = baseUrl + strUrl; - } - - if (!strUrl.isEmpty() && !strName.isEmpty()) { - sites.add(new Site(strUrl, strName, type)); - } - } - } - } - - return sites.toArray(new Site[sites.size()]); - } - - return null; - } - - /** - * Returns the first child element with the given XML local name. - * If xmlLocalName is null, returns the very first child element. - */ - private Node getFirstChild(Node node, String nsUri, String xmlLocalName) { - - for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI())) { - if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) { - return child; - } - } - } - - return null; - } - - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/CanceledByUserException.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/CanceledByUserException.java deleted file mode 100644 index 64ed8b12..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/CanceledByUserException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository; - -/** - * Exception thrown by {@link DownloadCache} and {@link UrlOpener} when a user - * cancels an HTTP Basic authentication or NTML authentication dialog. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class CanceledByUserException extends Exception { - private static final long serialVersionUID = -7669346110926032403L; - - public CanceledByUserException(String message) { - super(message); - } -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/DownloadCache.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/DownloadCache.java deleted file mode 100644 index 274c64ce..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/DownloadCache.java +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.utils.Pair; - -import org.apache.http.Header; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.message.BasicHeader; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * A simple cache for the XML resources handled by the SDK Manager. - *

- * Callers should use {@link #openDirectUrl} to download "large files" - * that should not be cached (like actual installation packages which are several MBs big) - * and call {@link #openCachedUrl(String, ITaskMonitor)} to download small XML files. - *

- * The cache can work in 3 different strategies (direct is a pass-through, fresh-cache is the - * default and tries to update resources if they are older than 10 minutes by respecting - * either ETag or Last-Modified, and finally server-cache is a strategy to always serve - * cached entries if present.) - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class DownloadCache { - - /* - * HTTP/1.1 references: - * - Possible headers: - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - * - Rules about conditional requests: - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4 - * - Error codes: - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1 - */ - - private static final boolean DEBUG = System.getenv("SDKMAN_DEBUG_CACHE") != null; //$NON-NLS-1$ - - /** Key for the Status-Code in the info properties. */ - private static final String KEY_STATUS_CODE = "Status-Code"; //$NON-NLS-1$ - /** Key for the URL in the info properties. */ - private static final String KEY_URL = "URL"; //$NON-NLS-1$ - - /** Prefix of binary files stored in the {@link SdkConstants#FD_CACHE} directory. */ - private static final String BIN_FILE_PREFIX = "sdkbin"; //$NON-NLS-1$ - /** Prefix of meta info files stored in the {@link SdkConstants#FD_CACHE} directory. */ - private static final String INFO_FILE_PREFIX = "sdkinf"; //$NON-NLS-1$ - /* Revision suffixed to the prefix. */ - private static final String REV_FILE_PREFIX = "-1_"; //$NON-NLS-1$ - - /** - * Minimum time before we consider a cached entry is potentially stale. - * Expressed in milliseconds. - *

- * When using the {@link Strategy#FRESH_CACHE}, the cache will not try to refresh - * a cached file if it's has been saved more recently than this time. - * When using the direct mode or the serve mode, the cache either doesn't serve - * cached files or always serves caches files so this expiration delay is not used. - *

- * Default is 10 minutes. - *

- * TODO: change for a dynamic preference later. - */ - private static final long MIN_TIME_EXPIRED_MS = 10*60*1000; - /** - * Maximum time before we consider a cache entry to be stale. - * Expressed in milliseconds. - *

- * When using the {@link Strategy#FRESH_CACHE}, entries that have no ETag - * or Last-Modified will be refreshed if their file timestamp is older than - * this value. - *

- * Default is 4 hours. - *

- * TODO: change for a dynamic preference later. - */ - private static final long MAX_TIME_EXPIRED_MS = 4*60*60*1000; - - /** - * The maximum file size we'll cache for "small" files. - * 640KB is more than enough and is already a stretch since these are read in memory. - * (The actual typical size of the files handled here is in the 4-64KB range.) - */ - private static final int MAX_SMALL_FILE_SIZE = 640 * 1024; - - /** - * HTTP Headers that are saved in an info file. - * For HTTP/1.1 header names, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - */ - private static final String[] INFO_HTTP_HEADERS = { - HttpHeaders.LAST_MODIFIED, - HttpHeaders.ETAG, - HttpHeaders.CONTENT_LENGTH, - HttpHeaders.DATE - }; - - private final IFileOp mFileOp; - private final File mCacheRoot; - private final Strategy mStrategy; - - public enum Strategy { - /** - * Exclusively serves data from the cache. If files are available in the - * cache, serve them as is (without trying to refresh them). If files are - * not available, they are not fetched at all. - */ - ONLY_CACHE, - /** - * If the files are available in the cache, serve them as-is, otherwise - * download them and return the cached version. No expiration or refresh - * is attempted if a file is in the cache. - */ - SERVE_CACHE, - /** - * If the files are available in the cache, check if there's an update - * (either using an e-tag check or comparing to the default time expiration). - * If files have expired or are not in the cache then download them and return - * the cached version. - */ - FRESH_CACHE, - /** - * Disables caching. URLs are always downloaded and returned directly. - * Downloaded streams aren't cached locally. - */ - DIRECT - } - - /** Creates a default instance of the URL cache */ - public DownloadCache(@NonNull Strategy strategy) { - this(new LegacyFileOp(), strategy); - } - - /** Creates a default instance of the URL cache */ - public DownloadCache(@NonNull IFileOp LegacyFileOp, @NonNull Strategy strategy) { - mFileOp = LegacyFileOp; - mCacheRoot = initCacheRoot(); - - // If this is defined in the environment, never use the cache. Useful for testing. - if (System.getenv("SDKMAN_DISABLE_CACHE") != null) { //$NON-NLS-1$ - strategy = Strategy.DIRECT; - } - - mStrategy = mCacheRoot == null ? Strategy.DIRECT : strategy; - } - - @NonNull - public Strategy getStrategy() { - return mStrategy; - } - - @Nullable - public File getCacheRoot() { - return mCacheRoot; - } - - /** - * Computes the size of the cached files. - * - * @return The sum of the byte size of the cached files. - */ - public long getCurrentSize() { - long size = 0; - - if (mCacheRoot != null) { - File[] files = mFileOp.listFiles(mCacheRoot); - for (File f : files) { - if (mFileOp.isFile(f)) { - String name = f.getName(); - if (name.startsWith(BIN_FILE_PREFIX) || name.startsWith(INFO_FILE_PREFIX)) { - size += f.length(); - } - } - } - } - - return size; - } - - /** - * Removes all cached files from the cache directory. - */ - public void clearCache() { - if (mCacheRoot != null) { - File[] files = mFileOp.listFiles(mCacheRoot); - for (File f : files) { - if (mFileOp.isFile(f)) { - String name = f.getName(); - if (name.startsWith(BIN_FILE_PREFIX) || name.startsWith(INFO_FILE_PREFIX)) { - mFileOp.delete(f); - } - } - } - } - } - - /** - * Removes all obsolete cached files from the cache directory - * that do not match the latest revision. - */ - public void clearOldCache() { - String prefix1 = BIN_FILE_PREFIX + REV_FILE_PREFIX; - String prefix2 = INFO_FILE_PREFIX + REV_FILE_PREFIX; - if (mCacheRoot != null) { - File[] files = mFileOp.listFiles(mCacheRoot); - for (File f : files) { - if (mFileOp.isFile(f)) { - String name = f.getName(); - if (name.startsWith(BIN_FILE_PREFIX) || - name.startsWith(INFO_FILE_PREFIX)) { - if (!name.startsWith(prefix1) && !name.startsWith(prefix2)) { - mFileOp.delete(f); - } - } - } - } - } - } - - /** - * Returns the directory to be used as a cache. - * Creates it if necessary. - * Makes it possible to disable or override the cache location in unit tests. - * - * @return An existing directory to use as a cache root dir, - * or null in case of error in which case the cache will be disabled. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - @Nullable - protected File initCacheRoot() { - try { - File root = new File(AndroidLocation.getFolder()); - root = new File(root, SdkConstants.FD_CACHE); - if (!mFileOp.exists(root)) { - mFileOp.mkdirs(root); - } - return root; - } catch (AndroidLocationException e) { - // No root? Disable the cache. - return null; - } - } - - /** - * Calls {@link UrlOpener#openUrl(String, boolean, ITaskMonitor, Header[])} - * to actually perform a download. - *

- * Isolated so that it can be overridden by unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - @NonNull - protected Pair openUrl( - @NonNull String url, - boolean needsMarkResetSupport, - @NonNull ITaskMonitor monitor, - @Nullable Header[] headers) throws IOException, CanceledByUserException { - return UrlOpener.openUrl(url, needsMarkResetSupport, monitor, headers); - } - - - /** - * Does a direct download of the given URL using {@link UrlOpener}. - * This does not check the download cache and does not attempt to cache the file. - * Instead the HttpClient library returns a progressive download stream. - *

- * For details on realm authentication and user/password handling, - * check the underlying {@link UrlOpener#openUrl(String, boolean, ITaskMonitor, Header[])} - * documentation. - *

- * The resulting input stream may not support mark/reset. - * - * @param urlString the URL string to be opened. - * @param headers An optional set of headers to pass when requesting the resource. Can be null. - * @param monitor {@link ITaskMonitor} which is related to this URL - * fetching. - * @return Returns a pair with a {@link InputStream} and an {@link HttpResponse}. - * The pair is never null. - * The input stream can be null in case of error, although in general the - * method will probably throw an exception instead. - * The caller should look at the response code's status and only accept the - * input stream if it's the desired code (e.g. 200 or 206). - * @throws IOException Exception thrown when there are problems retrieving - * the URL or its content. - * @throws CanceledByUserException Exception thrown if the user cancels the - * authentication dialog. - */ - @NonNull - public Pair openDirectUrl( - @NonNull String urlString, - @Nullable Header[] headers, - @NonNull ITaskMonitor monitor) - throws IOException, CanceledByUserException { - if (DEBUG) { - System.out.println(String.format("%s : Direct download", urlString)); //$NON-NLS-1$ - } - return openUrl( - urlString, - false /*needsMarkResetSupport*/, - monitor, - headers); - } - - /** - * This is a simplified convenience method that calls - * {@link #openDirectUrl(String, Header[], ITaskMonitor)} - * without passing any specific HTTP headers and returns the resulting input stream - * and the HTTP status code. - * See the original method's description for details on its behavior. - *

- * {@link #openDirectUrl(String, Header[], ITaskMonitor)} can accept customized - * HTTP headers to send with the requests and also returns the full HTTP - * response -- status line with code and protocol and all headers. - *

- * The resulting input stream may not support mark/reset. - * - * @param urlString the URL string to be opened. - * @param monitor {@link ITaskMonitor} which is related to this URL - * fetching. - * @return Returns a pair with a {@link InputStream} and an HTTP status code. - * The pair is never null. - * The input stream can be null in case of error, although in general the - * method will probably throw an exception instead. - * The caller should look at the response code's status and only accept the - * input stream if it's the desired code (e.g. 200 or 206). - * @throws IOException Exception thrown when there are problems retrieving - * the URL or its content. - * @throws CanceledByUserException Exception thrown if the user cancels the - * authentication dialog. - * @see #openDirectUrl(String, Header[], ITaskMonitor) - */ - @NonNull - public Pair openDirectUrl( - @NonNull String urlString, - @NonNull ITaskMonitor monitor) - throws IOException, CanceledByUserException { - if (DEBUG) { - System.out.println(String.format("%s : Direct download", urlString)); //$NON-NLS-1$ - } - Pair result = openUrl( - urlString, - false /*needsMarkResetSupport*/, - monitor, - null /*headers*/); - return Pair.of(result.getFirst(), result.getSecond().getStatusLine().getStatusCode()); - } - - /** - * Downloads a small file, typically XML manifests. - * The current {@link Strategy} governs whether the file is served as-is - * from the cache, potentially updated first or directly downloaded. - *

- * For large downloads (e.g. installable archives) please do not invoke the - * cache and instead use the {@link #openDirectUrl} method. - *

- * For details on realm authentication and user/password handling, - * check the underlying {@link UrlOpener#openUrl(String, boolean, ITaskMonitor, Header[])} - * documentation. - * - * @param urlString the URL string to be opened. - * @param monitor {@link ITaskMonitor} which is related to this URL - * fetching. - * @return Returns an {@link InputStream} holding the URL content. - * Returns null if there's no content (e.g. resource not found.) - * Returns null if the document is not cached and strategy is {@link Strategy#ONLY_CACHE}. - * @throws IOException Exception thrown when there are problems retrieving - * the URL or its content. - * @throws CanceledByUserException Exception thrown if the user cancels the - * authentication dialog. - */ - @NonNull - public InputStream openCachedUrl(@NonNull String urlString, @NonNull ITaskMonitor monitor) - throws IOException, CanceledByUserException { - // Don't cache in direct mode. - if (mStrategy == Strategy.DIRECT) { - Pair result = openUrl( - urlString, - true /*needsMarkResetSupport*/, - monitor, - null /*headers*/); - return result.getFirst(); - } - - File cached = new File(mCacheRoot, getCacheFilename(urlString)); - File info = new File(mCacheRoot, getInfoFilename(cached.getName())); - - boolean useCached = mFileOp.exists(cached); - - if (useCached && mStrategy == Strategy.FRESH_CACHE) { - // Check whether the file should be served from the cache or - // refreshed first. - - long cacheModifiedMs = mFileOp.lastModified(cached); /* last mod time in epoch/millis */ - boolean checkCache = true; - - Properties props = readInfo(info); - if (props == null) { - // No properties, no chocolate for you. - useCached = false; - } else { - long minExpiration = System.currentTimeMillis() - MIN_TIME_EXPIRED_MS; - checkCache = cacheModifiedMs < minExpiration; - - if (!checkCache && DEBUG) { - System.out.println(String.format( - "%s : Too fresh [%,d ms], not checking yet.", //$NON-NLS-1$ - urlString, cacheModifiedMs - minExpiration)); - } - } - - if (useCached && checkCache) { - assert props != null; - - // Right now we only support 200 codes and will requery all 404s. - String code = props.getProperty(KEY_STATUS_CODE, ""); //$NON-NLS-1$ - useCached = Integer.toString(HttpStatus.SC_OK).equals(code); - - if (!useCached && DEBUG) { - System.out.println(String.format( - "%s : cache disabled by code %s", //$NON-NLS-1$ - urlString, code)); - } - - if (useCached) { - // Do we have a valid Content-Length? If so, it should match the file size. - try { - long length = Long.parseLong(props.getProperty(HttpHeaders.CONTENT_LENGTH, - "-1")); //$NON-NLS-1$ - if (length >= 0) { - useCached = length == mFileOp.length(cached); - - if (!useCached && DEBUG) { - System.out.println(String.format( - "%s : cache disabled by length mismatch %d, expected %d", //$NON-NLS-1$ - urlString, length, cached.length())); - } - } - } catch (NumberFormatException ignore) {} - } - - if (useCached) { - // Do we have an ETag and/or a Last-Modified? - String etag = props.getProperty(HttpHeaders.ETAG); - String lastMod = props.getProperty(HttpHeaders.LAST_MODIFIED); - - if (etag != null || lastMod != null) { - // Details on how to use them is defined at - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4 - // Bottom line: - // - if there's an ETag, it should be used first with an - // If-None-Match header. That's a strong comparison for HTTP/1.1 servers. - // - otherwise use a Last-Modified if an If-Modified-Since header exists. - // In this case, we place both and the rules indicates a spec-abiding - // server should strongly match ETag and weakly the Modified-Since. - - // TODO there are some servers out there which report ETag/Last-Mod - // yet don't honor them when presented with a precondition. In this - // case we should identify it in the reply and invalidate ETag support - // for these servers and instead fallback on the pure-timeout case below. - - AtomicInteger statusCode = new AtomicInteger(0); - InputStream is = null; - List

headers = new ArrayList
(2); - - if (etag != null) { - headers.add(new BasicHeader(HttpHeaders.IF_NONE_MATCH, etag)); - } - - if (lastMod != null) { - headers.add(new BasicHeader(HttpHeaders.IF_MODIFIED_SINCE, lastMod)); - } - - if (!headers.isEmpty()) { - is = downloadAndCache(urlString, monitor, cached, info, - headers.toArray(new Header[headers.size()]), - statusCode); - } - - if (is != null && statusCode.get() == HttpStatus.SC_OK) { - // The resource was modified, the server said there was something - // new, which has been cached. We can return that to the caller. - return is; - } - - // If we get here, we should have is == null and code - // could be: - // - 304 for not-modified -- same resource, still available, in - // which case we'll use the cached one. - // - 404 -- resource doesn't exist anymore in which case there's - // no point in retrying. - // - For any other code, just retry a download. - - if (is != null) { - try { - is.close(); - } catch (Exception ignore) {} - is = null; - } - - if (statusCode.get() == HttpStatus.SC_NOT_MODIFIED) { - // Cached file was not modified. - // Change its timestamp for the next MIN_TIME_EXPIRED_MS check. - cached.setLastModified(System.currentTimeMillis()); - - // At this point useCached==true so we'll return - // the cached file below. - } else { - // URL fetch returned something other than 200 or 304. - // For 404, we're done, no need to check the server again. - // For all other codes, we'll retry a download below. - useCached = false; - if (statusCode.get() == HttpStatus.SC_NOT_FOUND) { - return null; - } - } - } else { - // If we don't have an Etag nor Last-Modified, let's use a - // basic file timestamp and compare to a 1 hour threshold. - - long maxExpiration = System.currentTimeMillis() - MAX_TIME_EXPIRED_MS; - useCached = cacheModifiedMs >= maxExpiration; - - if (!useCached && DEBUG) { - System.out.println(String.format( - "[%1$s] cache disabled by timestamp %2$tD %2$tT < %3$tD %3$tT", //$NON-NLS-1$ - urlString, cacheModifiedMs, maxExpiration)); - } - } - } - } - } - - if (useCached) { - // The caller needs an InputStream that supports the reset() operation. - // The default FileInputStream does not, so load the file into a byte - // array and return that. - try { - InputStream is = readCachedFile(cached); - if (is != null) { - if (DEBUG) { - System.out.println(String.format("%s : Use cached file", urlString)); //$NON-NLS-1$ - } - - return is; - } - } catch (IOException ignore) {} - } - - if (!useCached && mStrategy == Strategy.ONLY_CACHE) { - // We don't have a document to serve from the cache. - if (DEBUG) { - System.out.println(String.format("%s : file not in cache", urlString)); //$NON-NLS-1$ - } - return null; - } - - // If we're not using the cache, try to remove the cache and download again. - try { - mFileOp.delete(cached); - mFileOp.delete(info); - } catch (SecurityException ignore) {} - - return downloadAndCache(urlString, monitor, cached, info, - null /*headers*/, null /*statusCode*/); - } - - - - // -------------- - - @Nullable - private InputStream readCachedFile(@NonNull File cached) throws IOException { - InputStream is = null; - - int inc = 65536; - int curr = 0; - long len = cached.length(); - assert len < Integer.MAX_VALUE; - if (len >= MAX_SMALL_FILE_SIZE) { - // This is supposed to cache small files, not 2+ GB files. - return null; - } - byte[] result = new byte[(int) (len > 0 ? len : inc)]; - - try { - is = mFileOp.newFileInputStream(cached); - - int n; - while ((n = is.read(result, curr, result.length - curr)) != -1) { - curr += n; - if (curr == result.length) { - byte[] temp = new byte[curr + inc]; - System.arraycopy(result, 0, temp, 0, curr); - result = temp; - } - } - - return new ByteArrayInputStream(result, 0, curr); - - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ignore) {} - } - } - } - - /** - * Download, cache and return as an in-memory byte stream. - * The download is only done if the server returns 200/OK. - * On success, store an info file next to the download with - * a few headers. - *

- * This method deletes the cached file and the info file ONLY if it - * attempted a download and it failed to complete. It doesn't erase - * anything if there's no download because the server returned a 404 - * or 304 or similar. - * - * @return An in-memory byte buffer input stream for the downloaded - * and locally cached file, or null if nothing was downloaded - * (including if it was a 304 Not-Modified status code.) - */ - @Nullable - private InputStream downloadAndCache( - @NonNull String urlString, - @NonNull ITaskMonitor monitor, - @NonNull File cached, - @NonNull File info, - @Nullable Header[] headers, - @Nullable AtomicInteger outStatusCode) - throws FileNotFoundException, IOException, CanceledByUserException { - InputStream is = null; - OutputStream os = null; - - int inc = 65536; - int curr = 0; - byte[] result = new byte[inc]; - - try { - Pair r = - openUrl(urlString, true /*needsMarkResetSupport*/, monitor, headers); - - is = r.getFirst(); - HttpResponse response = r.getSecond(); - - if (DEBUG) { - System.out.println(String.format("%s : fetch: %s => %s", //$NON-NLS-1$ - urlString, - headers == null ? "" : Arrays.toString(headers), //$NON-NLS-1$ - response.getStatusLine())); - } - - int code = response.getStatusLine().getStatusCode(); - - if (outStatusCode != null) { - outStatusCode.set(code); - } - - if (code != HttpStatus.SC_OK) { - // Only a 200 response code makes sense here. - // Even the other 20x codes should not apply, e.g. no content or partial - // content are not statuses we want to handle and should never happen. - // (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1 for list) - return null; - } - - os = mFileOp.newFileOutputStream(cached); - - int n; - while ((n = is.read(result, curr, result.length - curr)) != -1) { - if (os != null && n > 0) { - os.write(result, curr, n); - } - - curr += n; - - if (os != null && curr > MAX_SMALL_FILE_SIZE) { - // If the file size exceeds our "small file size" threshold, - // stop caching. We don't want to fill the disk. - try { - os.close(); - } catch (IOException ignore) {} - try { - cached.delete(); - info.delete(); - } catch (SecurityException ignore) {} - os = null; - } - if (curr == result.length) { - byte[] temp = new byte[curr + inc]; - System.arraycopy(result, 0, temp, 0, curr); - result = temp; - } - } - - // Close the output stream, signaling it was stored properly. - if (os != null) { - try { - os.close(); - os = null; - - saveInfo(urlString, response, info); - } catch (IOException ignore) {} - } - - return new ByteArrayInputStream(result, 0, curr); - - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ignore) {} - } - if (os != null) { - try { - os.close(); - } catch (IOException ignore) {} - // If we get here with the output stream not null, it means there - // was an issue and we don't want to keep that file. We'll try to - // delete it. - try { - mFileOp.delete(cached); - mFileOp.delete(info); - } catch (SecurityException ignore) {} - } - } - } - - /** - * Saves part of the HTTP Response to the info file. - */ - private void saveInfo( - @NonNull String urlString, - @NonNull HttpResponse response, - @NonNull File info) throws IOException { - Properties props = new Properties(); - - // we don't need the status code & URL right now. - // Save it in case we want to have it later (e.g. to differentiate 200 and 404.) - props.setProperty(KEY_URL, urlString); - props.setProperty(KEY_STATUS_CODE, - Integer.toString(response.getStatusLine().getStatusCode())); - - for (String name : INFO_HTTP_HEADERS) { - Header h = response.getFirstHeader(name); - if (h != null) { - props.setProperty(name, h.getValue()); - } - } - - mFileOp.saveProperties(info, props, "## Meta data for SDK Manager cache. Do not modify."); //$NON-NLS-1$ - } - - /** - * Reads the info properties file. - * @return The properties found or null if there's no file or it can't be read. - */ - @Nullable - private Properties readInfo(@NonNull File info) { - if (mFileOp.exists(info)) { - return mFileOp.loadProperties(info); - } - return null; - } - - /** - * Computes the cache filename for the given URL. - * The filename uses the {@link #BIN_FILE_PREFIX}, the full URL string's hashcode and - * a sanitized portion of the URL filename. The returned filename is never - * more than 64 characters to ensure maximum file system compatibility. - * - * @param urlString The download URL. - * @return A leaf filename for the cached download file. - */ - @NonNull - private String getCacheFilename(@NonNull String urlString) { - - int code = 0; - for (int i = 0, j = urlString.length(); i < j; i++) { - code = code * 31 + urlString.charAt(i); - } - String hash = String.format("%08x", code); - - String leaf = urlString.toLowerCase(Locale.US); - if (leaf.length() >= 2) { - int index = urlString.lastIndexOf('/', leaf.length() - 2); - leaf = urlString.substring(index + 1); - } - - leaf = leaf.replaceAll("[^a-z0-9_-]+", "_"); - leaf = leaf.replaceAll("__+", "_"); - - leaf = hash + '-' + leaf; - String prefix = BIN_FILE_PREFIX + REV_FILE_PREFIX; - int n = 64 - prefix.length(); - if (leaf.length() > n) { - leaf = leaf.substring(0, n); - } - - return prefix + leaf; - } - - @NonNull - private String getInfoFilename(@NonNull String cacheFilename) { - return cacheFilename.replaceFirst(BIN_FILE_PREFIX, INFO_FILE_PREFIX); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/LocalSdkParser.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/LocalSdkParser.java deleted file mode 100644 index 69064eff..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/LocalSdkParser.java +++ /dev/null @@ -1,804 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.io.FileWrapper; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.ISystemImage.LocationType; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.androidTarget.PlatformTarget; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.internal.repository.packages.BuildToolPackage; -import com.android.sdklib.internal.repository.packages.DocPackage; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SamplePackage; -import com.android.sdklib.internal.repository.packages.SourcePackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.AddonManifestIniProps; -import com.android.sdklib.repository.descriptors.PkgType; -import com.android.utils.ILogger; -import com.android.utils.Pair; -import com.google.common.collect.Lists; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * Scans a local SDK to find which packages are currently installed. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class LocalSdkParser { - - private Package[] mPackages; - - /** Parse all SDK folders. */ - public static final int PARSE_ALL = PkgType.PKG_ALL_INT; - /** Parse the SDK/tools folder. */ - public static final int PARSE_TOOLS = PkgType.PKG_TOOLS.getIntValue(); - /** Parse the SDK/platform-tools folder */ - public static final int PARSE_PLATFORM_TOOLS = PkgType.PKG_PLATFORM_TOOLS.getIntValue(); - /** Parse the SDK/docs folder. */ - public static final int PARSE_DOCS = PkgType.PKG_DOC.getIntValue(); - /** - * Equivalent to parsing the SDK/platforms folder but does so - * by using the valid targets loaded by the {@link SdkManager}. - * Parsing the platforms also parses the SDK/system-images folder. - */ - public static final int PARSE_PLATFORMS = PkgType.PKG_PLATFORM.getIntValue(); - /** - * Equivalent to parsing the SDK/addons folder but does so - * by using the valid targets loaded by the {@link SdkManager}. - */ - public static final int PARSE_ADDONS = PkgType.PKG_ADDON.getIntValue(); - /** Parse the SDK/samples folder. - * Note: this will not detect samples located in the SDK/extras packages. */ - public static final int PARSE_SAMPLES = PkgType.PKG_SAMPLE.getIntValue(); - /** Parse the SDK/sources folder. */ - public static final int PARSE_SOURCES = PkgType.PKG_SOURCE.getIntValue(); - /** Parse the SDK/extras folder. */ - public static final int PARSE_EXTRAS = PkgType.PKG_EXTRA.getIntValue(); - /** Parse the SDK/build-tools folder. */ - public static final int PARSE_BUILD_TOOLS = PkgType.PKG_BUILD_TOOLS.getIntValue(); - - public LocalSdkParser() { - // pass - } - - /** - * Returns the packages found by the last call to {@link #parseSdk}. - *

- * This returns initially returns null. - * Once the parseSdk() method has been called, this returns a possibly empty but non-null array. - */ - public Package[] getPackages() { - return mPackages; - } - - /** - * Clear the internal packages list. After this call, {@link #getPackages()} will return - * null till {@link #parseSdk} is called. - */ - public void clearPackages() { - mPackages = null; - } - - /** - * Scan the give SDK to find all the packages already installed at this location. - *

- * Store the packages internally. You can use {@link #getPackages()} to retrieve them - * at any time later. - *

- * Equivalent to calling {@code parseSdk(..., PARSE_ALL, ...); } - * - * @param osSdkRoot The path to the SDK folder, typically {@code sdkManager.getLocation()}. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @param monitor A monitor to track progress. Cannot be null. - * @return The packages found. Can be retrieved later using {@link #getPackages()}. - */ - @NonNull - public Package[] parseSdk( - @NonNull String osSdkRoot, - @NonNull SdkManager sdkManager, - @NonNull ITaskMonitor monitor) { - return parseSdk(osSdkRoot, sdkManager, PARSE_ALL, monitor); - } - - /** - * Scan the give SDK to find all the packages already installed at this location. - *

- * Store the packages internally. You can use {@link #getPackages()} to retrieve them - * at any time later. - * - * @param osSdkRoot The path to the SDK folder, typically {@code sdkManager.getLocation()}. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @param parseFilter Either {@link #PARSE_ALL} or an ORed combination of the other - * {@code PARSE_} constants to indicate what should be parsed. - * @param monitor A monitor to track progress. Cannot be null. - * @return The packages found. Can be retrieved later using {@link #getPackages()}. - */ - @NonNull - public Package[] parseSdk( - @NonNull String osSdkRoot, - @NonNull SdkManager sdkManager, - int parseFilter, - @NonNull ITaskMonitor monitor) { - ArrayList packages = new ArrayList(); - HashSet visited = new HashSet(); - - monitor.setProgressMax(11); - - File dir = null; - Package pkg = null; - - if ((parseFilter & PARSE_DOCS) != 0) { - dir = new File(osSdkRoot, SdkConstants.FD_DOCS); - pkg = scanDoc(dir, monitor); - if (pkg != null) { - packages.add(pkg); - visited.add(dir); - } - } - monitor.incProgress(1); - - if ((parseFilter & PARSE_TOOLS) != 0) { - dir = new File(osSdkRoot, SdkConstants.FD_TOOLS); - pkg = scanTools(dir, monitor); - if (pkg != null) { - packages.add(pkg); - visited.add(dir); - } - } - monitor.incProgress(1); - - if ((parseFilter & PARSE_PLATFORM_TOOLS) != 0) { - dir = new File(osSdkRoot, SdkConstants.FD_PLATFORM_TOOLS); - pkg = scanPlatformTools(dir, monitor); - if (pkg != null) { - packages.add(pkg); - visited.add(dir); - } - } - monitor.incProgress(1); - - if ((parseFilter & PARSE_BUILD_TOOLS) != 0) { - scanBuildTools(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - - // for platforms, add-ons and samples, rely on the SdkManager parser - if ((parseFilter & (PARSE_ADDONS | PARSE_PLATFORMS)) != 0) { - File samplesRoot = new File(osSdkRoot, SdkConstants.FD_SAMPLES); - - for(IAndroidTarget target : sdkManager.getTargets()) { - Properties props = parseProperties(new File(target.getLocation(), - SdkConstants.FN_SOURCE_PROP)); - - try { - pkg = null; - if (target.isPlatform() && (parseFilter & PARSE_PLATFORMS) != 0) { - pkg = PlatformPackage.create(target, props); - - if (samplesRoot.isDirectory()) { - // Get the samples dir for a platform if it is located in the new - // root /samples dir. We purposely ignore "old" samples that are - // located under the platform dir. - File samplesDir = new File(target.getPath(IAndroidTarget.SAMPLES)); - if (samplesDir.exists() && - samplesDir.getParentFile().equals(samplesRoot)) { - Properties samplesProps = parseProperties( - new File(samplesDir, SdkConstants.FN_SOURCE_PROP)); - if (samplesProps != null) { - Package pkg2 = SamplePackage.create(target, samplesProps); - packages.add(pkg2); - } - visited.add(samplesDir); - } - } - } else if ((parseFilter & PARSE_ADDONS) != 0) { - pkg = AddonPackage.create(target, props); - } - - if (pkg != null) { - for (ISystemImage systemImage : target.getSystemImages()) { - if (systemImage.getLocationType() == LocationType.IN_SYSTEM_IMAGE) { - File siDir = systemImage.getLocation(); - if (siDir.isDirectory()) { - Properties siProps = parseProperties( - new File(siDir, SdkConstants.FN_SOURCE_PROP)); - Package pkg2 = new SystemImagePackage( - target.getVersion(), - 0 /*rev*/, // use the one from siProps - systemImage.getAbiType(), - siProps, - siDir.getAbsolutePath()); - packages.add(pkg2); - visited.add(siDir); - } - } - } - } - - } catch (Exception e) { - monitor.error(e, null); - } - - if (pkg != null) { - packages.add(pkg); - visited.add(new File(target.getLocation())); - } - } - } - monitor.incProgress(1); - - if ((parseFilter & PARSE_PLATFORMS) != 0) { - scanMissingSystemImages(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - if ((parseFilter & PARSE_ADDONS) != 0) { - scanMissingAddons(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - if ((parseFilter & PARSE_SAMPLES) != 0) { - scanMissingSamples(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - if ((parseFilter & PARSE_EXTRAS) != 0) { - scanExtras(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - if ((parseFilter & PARSE_EXTRAS) != 0) { - scanExtrasDirectory(osSdkRoot, visited, packages, monitor); - } - monitor.incProgress(1); - if ((parseFilter & PARSE_SOURCES) != 0) { - scanSources(sdkManager, visited, packages, monitor); - } - monitor.incProgress(1); - - Collections.sort(packages); - - mPackages = packages.toArray(new Package[packages.size()]); - return mPackages; - } - - /** - * Find any directory in the /extras/vendors/path folders for extra packages. - * This isn't a recursive search. - */ - private void scanExtras(SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File root = new File(sdkManager.getLocation(), SdkConstants.FD_EXTRAS); - - for (File vendor : listFilesNonNull(root)) { - if (vendor.isDirectory()) { - scanExtrasDirectory(vendor.getAbsolutePath(), visited, packages, log); - } - } - } - - /** - * Find any other directory in the given "root" directory that hasn't been visited yet - * and assume they contain extra packages. This is not a recursive search. - */ - private void scanExtrasDirectory(String extrasRoot, - HashSet visited, - ArrayList packages, - ILogger log) { - File root = new File(extrasRoot); - - for (File dir : listFilesNonNull(root)) { - if (dir.isDirectory() && !visited.contains(dir)) { - Properties props = parseProperties(new File(dir, SdkConstants.FN_SOURCE_PROP)); - if (props != null) { - try { - Package pkg = ExtraPackage.create( - null, //source - props, //properties - null, //vendor - dir.getName(), //path - 0, //revision - null, //license - null, //description - null, //descUrl - dir.getPath() //archiveOsPath - ); - - packages.add(pkg); - visited.add(dir); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - } - - /** - * Find any other sub-directories under the /samples root that hasn't been visited yet - * and assume they contain sample packages. This is not a recursive search. - *

- * The use case is to find samples dirs under /samples when their target isn't loaded. - */ - private void scanMissingSamples(SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File root = new File(sdkManager.getLocation()); - root = new File(root, SdkConstants.FD_SAMPLES); - - for (File dir : listFilesNonNull(root)) { - if (dir.isDirectory() && !visited.contains(dir)) { - Properties props = parseProperties(new File(dir, SdkConstants.FN_SOURCE_PROP)); - if (props != null) { - try { - Package pkg = SamplePackage.create(dir.getAbsolutePath(), props); - packages.add(pkg); - visited.add(dir); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - } - - /** - * The sdk manager only lists valid addons. However here we also want to find "broken" - * addons, i.e. addons that failed to load for some reason. - *

- * Find any other sub-directories under the /add-ons root that hasn't been visited yet - * and assume they contain broken addons. - */ - private void scanMissingAddons(SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File addons = new File(new File(sdkManager.getLocation()), SdkConstants.FD_ADDONS); - - for (File dir : listFilesNonNull(addons)) { - if (dir.isDirectory() && !visited.contains(dir)) { - Pair, String> infos = - parseAddonProperties(dir, sdkManager.getTargets(), log); - Properties sourceProps = - parseProperties(new File(dir, SdkConstants.FN_SOURCE_PROP)); - - Map addonProps = infos.getFirst(); - String error = infos.getSecond(); - try { - Package pkg = AddonPackage.createBroken(dir.getAbsolutePath(), - sourceProps, - addonProps, - error); - packages.add(pkg); - visited.add(dir); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - - /** - * Parses the add-on properties and decodes any error that occurs when - * loading an addon. - * - * @param addonDir the location of the addon directory. - * @param targetList The list of Android target that were already loaded - * from the SDK. - * @param log the ILogger object receiving warning/error from the parsing. - * @return A pair with the property map and an error string. Both can be - * null but not at the same time. If a non-null error is present - * then the property map must be ignored. The error should be - * translatable as it might show up in the SdkManager UI. - */ - @Deprecated // Copied from SdkManager.java, dup of LocalAddonPkgInfo.parseAddonProperties. - @NonNull - public static Pair, String> parseAddonProperties( - @NonNull File addonDir, @NonNull IAndroidTarget[] targetList, - @NonNull ILogger log) { - Map propertyMap = null; - String error = null; - - FileWrapper addOnManifest = new FileWrapper(addonDir, - SdkConstants.FN_MANIFEST_INI); - - do { - if (!addOnManifest.isFile()) { - error = String.format("File not found: %1$s", - SdkConstants.FN_MANIFEST_INI); - break; - } - - propertyMap = ProjectProperties.parsePropertyFile(addOnManifest, - log); - if (propertyMap == null) { - error = String.format("Failed to parse properties from %1$s", - SdkConstants.FN_MANIFEST_INI); - break; - } - - // look for some specific values in the map. - // we require name, vendor, and api - String name = propertyMap.get(AddonManifestIniProps.ADDON_NAME); - if (name == null) { - error = String.format("'%1$s' is missing from %2$s.", - AddonManifestIniProps.ADDON_NAME, - SdkConstants.FN_MANIFEST_INI); - break; - } - - String vendor = propertyMap.get(AddonManifestIniProps.ADDON_VENDOR); - if (vendor == null) { - error = String.format("'%1$s' is missing from %2$s.", - AddonManifestIniProps.ADDON_VENDOR, - SdkConstants.FN_MANIFEST_INI); - break; - } - - String api = propertyMap.get(AddonManifestIniProps.ADDON_API); - if (api == null) { - error = String.format("'%1$s' is missing from %2$s.", - AddonManifestIniProps.ADDON_API, - SdkConstants.FN_MANIFEST_INI); - break; - } - - // Look for a platform that has a matching api level or codename. - PlatformTarget baseTarget = null; - for (IAndroidTarget target : targetList) { - if (target.isPlatform() && target.getVersion().equals(api)) { - baseTarget = (PlatformTarget) target; - break; - } - } - - if (baseTarget == null) { - error = String.format( - "Unable to find base platform with API level '%1$s'", - api); - break; - } - - // get the add-on revision - String revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION); - if (revision == null) { - revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION_OLD); - } - if (revision != null) { - try { - Integer.parseInt(revision); - } catch (NumberFormatException e) { - // looks like revision does not parse to a number. - error = String.format( - "%1$s is not a valid number in %2$s.", - AddonManifestIniProps.ADDON_REVISION, - SdkConstants.FN_BUILD_PROP); - break; - } - } - - } while (false); - - return Pair.of(propertyMap, error); - } - - - /** - * The sdk manager only lists valid system image via its addons or platform targets. - * However here we also want to find "broken" system images, that is system images - * that are located in the sdk/system-images folder but somehow not loaded properly. - */ - private void scanMissingSystemImages(SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File siRoot = new File(sdkManager.getLocation(), SdkConstants.FD_SYSTEM_IMAGES); - - // The system-images folder contains a list of platform folders. - for (File platformDir : listFilesNonNull(siRoot)) { - if (platformDir.isDirectory() && !visited.contains(platformDir)) { - visited.add(platformDir); - - // In the platform directory, we expect a list of abi folders - // or a list of tag/abi folders. Basically parse any folder that has - // a source.prop file within 2 levels. - List propFiles = Lists.newArrayList(); - - for (File dir1 : listFilesNonNull(platformDir)) { - if (dir1.isDirectory() && !visited.contains(dir1)) { - visited.add(dir1); - File prop1 = new File(dir1, SdkConstants.FN_SOURCE_PROP); - if (prop1.isFile()) { - propFiles.add(prop1); - } else { - for (File dir2 : listFilesNonNull(dir1)) { - if (dir2.isDirectory() && !visited.contains(dir2)) { - visited.add(dir2); - File prop2 = new File(dir2, SdkConstants.FN_SOURCE_PROP); - if (prop2.isFile()) { - propFiles.add(prop2); - } - } - } - } - } - } - - for (File propFile : propFiles) { - Properties props = parseProperties(propFile); - try { - Package pkg = SystemImagePackage.createBroken(propFile.getParentFile(), - props); - packages.add(pkg); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - } - - /** - * Scan the sources/folders and register valid as well as broken source packages. - */ - private void scanSources(SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File srcRoot = new File(sdkManager.getLocation(), SdkConstants.FD_PKG_SOURCES); - - // The sources folder contains a list of platform folders. - for (File platformDir : listFilesNonNull(srcRoot)) { - if (platformDir.isDirectory() && !visited.contains(platformDir)) { - visited.add(platformDir); - - // Ignore empty directories - File[] srcFiles = platformDir.listFiles(); - if (srcFiles != null && srcFiles.length > 0) { - Properties props = - parseProperties(new File(platformDir, SdkConstants.FN_SOURCE_PROP)); - - try { - Package pkg = SourcePackage.create(platformDir, props); - packages.add(pkg); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - } - - /** - * Try to find a tools package at the given location. - * Returns null if not found. - */ - private Package scanTools(File toolFolder, ILogger log) { - // Can we find some properties? - Properties props = parseProperties(new File(toolFolder, SdkConstants.FN_SOURCE_PROP)); - - // We're not going to check that all tools are present. At the very least - // we should expect to find android and an emulator adapted to the current OS. - boolean hasEmulator = false; - boolean hasAndroid = false; - String android1 = SdkConstants.androidCmdName().replace(".bat", ".exe"); - String android2 = android1.indexOf('.') == -1 ? null : android1.replace(".exe", ".bat"); - for (File file : listFilesNonNull(toolFolder)) { - String name = file.getName(); - if (SdkConstants.FN_EMULATOR.equals(name)) { - hasEmulator = true; - } - if (android1.equals(name) || (android2 != null && android2.equals(name))) { - hasAndroid = true; - } - } - - if (!hasAndroid || !hasEmulator) { - return null; - } - - // Create our package. use the properties if we found any. - try { - Package pkg = ToolPackage.create( - null, //source - props, //properties - 0, //revision - null, //license - "Tools", //description - null, //descUrl - toolFolder.getPath() //archiveOsPath - ); - - return pkg; - } catch (Exception e) { - log.error(e, null); - } - return null; - } - - /** - * Try to find a platform-tools package at the given location. - * Returns null if not found. - */ - private Package scanPlatformTools(File platformToolsFolder, ILogger log) { - // Can we find some properties? - Properties props = parseProperties(new File(platformToolsFolder, - SdkConstants.FN_SOURCE_PROP)); - - // We're not going to check that all tools are present. At the very least - // we should expect to find adb, aidl, aapt and dx (adapted to the current OS). - - if (platformToolsFolder.listFiles() == null) { - // ListFiles is null if the directory doesn't even exist. - // Not going to find anything in there... - return null; - } - - // Create our package. use the properties if we found any. - try { - Package pkg = PlatformToolPackage.create( - null, //source - props, //properties - 0, //revision - null, //license - "Platform Tools", //description - null, //descUrl - platformToolsFolder.getPath() //archiveOsPath - ); - - return pkg; - } catch (Exception e) { - log.error(e, null); - } - return null; - } - - /** - * Scan the build-tool/folders and register valid as well as broken build tool packages. - */ - private void scanBuildTools( - SdkManager sdkManager, - HashSet visited, - ArrayList packages, - ILogger log) { - File buildToolRoot = new File(sdkManager.getLocation(), SdkConstants.FD_BUILD_TOOLS); - - // The build-tool root folder contains a list of revisioned folders. - for (File buildToolDir : listFilesNonNull(buildToolRoot)) { - if (buildToolDir.isDirectory() && !visited.contains(buildToolDir)) { - visited.add(buildToolDir); - - // Ignore empty directories - File[] srcFiles = buildToolDir.listFiles(); - if (srcFiles != null && srcFiles.length > 0) { - Properties props = - parseProperties(new File(buildToolDir, SdkConstants.FN_SOURCE_PROP)); - - try { - Package pkg = BuildToolPackage.create(buildToolDir, props); - packages.add(pkg); - } catch (Exception e) { - log.error(e, null); - } - } - } - } - } - - /** - * Try to find a docs package at the given location. - * Returns null if not found. - */ - private Package scanDoc(File docFolder, ILogger log) { - // Can we find some properties? - Properties props = parseProperties(new File(docFolder, SdkConstants.FN_SOURCE_PROP)); - - // To start with, a doc folder should have an "index.html" to be acceptable. - // We don't actually check the content of the file. - if (new File(docFolder, "index.html").isFile()) { - try { - Package pkg = DocPackage.create( - null, //source - props, //properties - 0, //apiLevel - null, //codename - 0, //revision - null, //license - null, //description - null, //descUrl - docFolder.getPath() //archiveOsPath - ); - - return pkg; - } catch (Exception e) { - log.error(e, null); - } - } - - return null; - } - - /** - * Parses the given file as properties file if it exists. - * Returns null if the file does not exist, cannot be parsed or has no properties. - */ - private Properties parseProperties(File propsFile) { - FileInputStream fis = null; - try { - if (propsFile.exists()) { - fis = new FileInputStream(propsFile); - - Properties props = new Properties(); - props.load(fis); - - // To be valid, there must be at least one property in it. - if (!props.isEmpty()) { - return props; - } - } - - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - } - } - } - return null; - } - - /** - * Helper method that calls {@link File#listFiles()} and returns - * a non-null empty list if the input is not a directory or has - * no files. - */ - @NonNull - private static File[] listFilesNonNull(@NonNull File dir) { - if (dir.isDirectory()) { - File[] files = dir.listFiles(); - if (files != null) { - return files; - } - } - return LegacyFileOp.EMPTY_FILE_ARRAY; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/NullTaskMonitor.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/NullTaskMonitor.java deleted file mode 100644 index 27269541..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/NullTaskMonitor.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.utils.ILogger; -import com.android.utils.NullLogger; - - -/** - * A no-op implementation of the {@link ITaskMonitor} interface. - *

- * This can be passed to methods that require a monitor when the caller doesn't - * have any UI to update or means to report tracked progress. - * A custom {@link ILogger} is used. Clients could use {@link NullLogger} if - * they really don't care about the logging either. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class NullTaskMonitor implements ITaskMonitor { - - private final ILogger mLog; - - /** - * Creates a no-op {@link ITaskMonitor} that defers logging to the specified - * logger. - *

- * This can be passed to methods that require a monitor when the caller doesn't - * have any UI to update or means to report tracked progress. - * - * @param log An {@link ILogger}. Must not be null. Consider using {@link NullLogger}. - */ - public NullTaskMonitor(ILogger log) { - mLog = log; - } - - @Override - public void setDescription(String format, Object...args) { - // pass - } - - @Override - public void log(String format, Object...args) { - mLog.info(format, args); - } - - @Override - public void logError(String format, Object...args) { - mLog.error(null /*throwable*/, format, args); - } - - @Override - public void logVerbose(String format, Object...args) { - mLog.verbose(format, args); - } - - @Override - public void setProgressMax(int max) { - // pass - } - - @Override - public int getProgressMax() { - return 0; - } - - @Override - public void incProgress(int delta) { - // pass - } - - /** Always return 1. */ - @Override - public int getProgress() { - return 1; - } - - /** Always return false. */ - @Override - public boolean isCancelRequested() { - return false; - } - - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - return this; - } - - /** Always return false. */ - @Override - public boolean displayPrompt(final String title, final String message) { - return false; - } - - /** Always return null. */ - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - return null; - } - - // --- ILogger --- - - @Override - public void error(@Nullable Throwable t, @Nullable String errorFormat, Object... args) { - mLog.error(t, errorFormat, args); - } - - @Override - public void warning(@NonNull String warningFormat, Object... args) { - mLog.warning(warningFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - mLog.info(msgFormat, args); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - mLog.verbose(msgFormat, args); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/SdkStats.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/SdkStats.java deleted file mode 100644 index cb1af741..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/SdkStats.java +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository; - -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.io.NonClosingInputStream; -import com.android.io.NonClosingInputStream.CloseBehavior; -import com.android.sdklib.repository.SdkStatsConstants; -import com.android.utils.SparseArray; - -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.UnknownHostException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.net.ssl.SSLKeyException; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; - - -/** - * Retrieves stats on platforms. - *

- * This returns information stored on the repository in a different XML file - * and isn't directly tied to the existence of the listed platforms. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkStats { - - public static class PlatformStatBase { - private final int mApiLevel; - private final String mVersionName; - private final String mCodeName; - private final float mShare; - - public PlatformStatBase(int apiLevel, - String versionName, - String codeName, - float share) { - mApiLevel = apiLevel; - mVersionName = versionName; - mCodeName = codeName; - mShare = share; - } - - /** The Android API Level for the platform. An int > 0. */ - public int getApiLevel() { - return mApiLevel; - } - - /** The official codename for this platform, for example "Cupcake". */ - public String getCodeName() { - return mCodeName; - } - - /** The official version name of this platform, for example "Android 1.5". */ - public String getVersionName() { - return mVersionName; - } - - /** An approximate share percentage of this platform and all the - * platforms of lower API level. */ - public float getShare() { - return mShare; - } - - /** Returns a string representation of this object, for debugging purposes. */ - @Override - public String toString() { - return String.format("api=%d, code=%s, vers=%s, share=%.1f%%", //$NON-NLS-1$ - mApiLevel, mCodeName, mVersionName, mShare); - } - } - - public static class PlatformStat extends PlatformStatBase { - private final float mAccumShare; - - public PlatformStat(int apiLevel, - String versionName, - String codeName, - float share, - float accumShare) { - super(apiLevel, versionName, codeName, share); - mAccumShare = accumShare; - } - - public PlatformStat(PlatformStatBase base, float accumShare) { - super(base.getApiLevel(), - base.getVersionName(), - base.getCodeName(), - base.getShare()); - mAccumShare = accumShare; - } - - /** The accumulated approximate share percentage of that platform. */ - public float getAccumShare() { - return mAccumShare; - } - - /** Returns a string representation of this object, for debugging purposes. */ - @Override - public String toString() { - return String.format("", super.toString(), mAccumShare); - } - } - - private final SparseArray mStats = new SparseArray(); - - public SdkStats() { - } - - public SparseArray getStats() { - return mStats; - } - - public void load(DownloadCache cache, boolean forceHttp, ITaskMonitor monitor) { - - String url = SdkStatsConstants.URL_STATS; - - if (forceHttp) { - url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - monitor.setProgressMax(5); - monitor.setDescription("Fetching %1$s", url); - monitor.incProgress(1); - - Exception[] exception = new Exception[] { null }; - Boolean[] validatorFound = new Boolean[] { Boolean.FALSE }; - String[] validationError = new String[] { null }; - Document validatedDoc = null; - String validatedUri = null; - - InputStream xml = fetchXmlUrl(url, cache, monitor.createSubMonitor(1), exception); - - if (xml != null) { - monitor.setDescription("Validate XML"); - - // Explore the XML to find the potential XML schema version - int version = getXmlSchemaVersion(xml); - - if (version >= 1 && version <= SdkStatsConstants.NS_LATEST_VERSION) { - // This should be a version we can handle. Try to validate it - // and report any error as invalid XML syntax, - - String uri = validateXml(xml, url, version, validationError, validatorFound); - if (uri != null) { - // Validation was successful - validatedDoc = getDocument(xml, monitor); - validatedUri = uri; - - } - } else if (version > SdkStatsConstants.NS_LATEST_VERSION) { - // The schema used is more recent than what is supported by this tool. - // We don't have an upgrade-path support yet, so simply ignore the document. - closeStream(xml); - return; - } - } - - // If any exception was handled during the URL fetch, display it now. - if (exception[0] != null) { - String reason = null; - if (exception[0] instanceof FileNotFoundException) { - // FNF has no useful getMessage, so we need to special handle it. - reason = "File not found"; - } else if (exception[0] instanceof UnknownHostException && - exception[0].getMessage() != null) { - // This has no useful getMessage yet could really use one - reason = String.format("Unknown Host %1$s", exception[0].getMessage()); - } else if (exception[0] instanceof SSLKeyException) { - // That's a common error and we have a pref for it. - reason = "HTTPS SSL error. You might want to force download through HTTP in the settings."; - } else if (exception[0].getMessage() != null) { - reason = exception[0].getMessage(); - } else { - // We don't know what's wrong. Let's give the exception class at least. - reason = String.format("Unknown (%1$s)", exception[0].getClass().getName()); - } - - monitor.logError("Failed to fetch URL %1$s, reason: %2$s", url, reason); - } - - if (validationError[0] != null) { - monitor.logError("%s", validationError[0]); //$NON-NLS-1$ - } - - // Stop here if we failed to validate the XML. We don't want to load it. - if (validatedDoc == null) { - closeStream(xml); - return; - } - - monitor.incProgress(1); - - if (xml != null) { - monitor.setDescription("Parse XML"); - monitor.incProgress(1); - parseStatsDocument(validatedDoc, validatedUri, monitor); - } - - // done - monitor.incProgress(1); - closeStream(xml); - } - - /** - * Fetches the document at the given URL and returns it as a stream. Returns - * null if anything wrong happens. - * - * @param urlString The URL to load, as a string. - * @param monitor {@link ITaskMonitor} related to this URL. - * @param outException If non null, where to store any exception that - * happens during the fetch. - * @see UrlOpener UrlOpener, which handles all URL logic. - */ - private InputStream fetchXmlUrl(String urlString, - DownloadCache cache, - ITaskMonitor monitor, - Exception[] outException) { - try { - InputStream xml = cache.openCachedUrl(urlString, monitor); - if (xml != null) { - xml.mark(500000); - xml = new NonClosingInputStream(xml); - ((NonClosingInputStream) xml).setCloseBehavior(CloseBehavior.RESET); - } - return xml; - } catch (Exception e) { - if (outException != null) { - outException[0] = e; - } - } - - return null; - } - - /** - * Closes the stream, ignore any exception from InputStream.close(). - * If the stream is a NonClosingInputStream, sets it to CloseBehavior.CLOSE first. - */ - private void closeStream(InputStream is) { - if (is != null) { - if (is instanceof NonClosingInputStream) { - ((NonClosingInputStream) is).setCloseBehavior(CloseBehavior.CLOSE); - } - try { - is.close(); - } catch (IOException ignore) {} - } - } - - /** - * Manually parses the root element of the XML to extract the schema version - * at the end of the xmlns:sdk="http://schemas.android.com/sdk/android/addons-list/$N" - * declaration. - * - * @return 1..{@link SdkStatsConstants#NS_LATEST_VERSION} for a valid schema version - * or 0 if no schema could be found. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected int getXmlSchemaVersion(InputStream xml) { - if (xml == null) { - return 0; - } - - // Get an XML document - Document doc = null; - try { - xml.reset(); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(false); - factory.setValidating(false); - - // Parse the old document using a non namespace aware builder - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - - // We don't want the default handler which prints errors to stderr. - builder.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException e) throws SAXException { - // pass - } - @Override - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - @Override - public void error(SAXParseException e) throws SAXException { - throw e; - } - }); - - doc = builder.parse(xml); - - // Prepare a new document using a namespace aware builder - factory.setNamespaceAware(true); - builder = factory.newDocumentBuilder(); - - } catch (Exception e) { - // Failed to reset XML stream - // Failed to get builder factor - // Failed to create XML document builder - // Failed to parse XML document - // Failed to read XML document - } - - if (doc == null) { - return 0; - } - - // Check the root element is an XML with at least the following properties: - // - // - // Note that we don't have namespace support enabled, we just do it manually. - - Pattern nsPattern = Pattern.compile(SdkStatsConstants.NS_PATTERN); - - String prefix = null; - for (Node child = doc.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - prefix = null; - String name = child.getNodeName(); - int pos = name.indexOf(':'); - if (pos > 0 && pos < name.length() - 1) { - prefix = name.substring(0, pos); - name = name.substring(pos + 1); - } - if (SdkStatsConstants.NODE_SDK_STATS.equals(name)) { - NamedNodeMap attrs = child.getAttributes(); - String xmlns = "xmlns"; //$NON-NLS-1$ - if (prefix != null) { - xmlns += ":" + prefix; //$NON-NLS-1$ - } - Node attr = attrs.getNamedItem(xmlns); - if (attr != null) { - String uri = attr.getNodeValue(); - if (uri != null) { - Matcher m = nsPattern.matcher(uri); - if (m.matches()) { - String version = m.group(1); - try { - return Integer.parseInt(version); - } catch (NumberFormatException e) { - return 0; - } - } - } - } - } - } - } - - return 0; - } - - /** - * Validates this XML against one of the requested SDK Repository schemas. - * If the XML was correctly validated, returns the schema that worked. - * If it doesn't validate, returns null and stores the error in outError[0]. - * If we can't find a validator, returns null and set validatorFound[0] to false. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected String validateXml(InputStream xml, String url, int version, - String[] outError, Boolean[] validatorFound) { - - if (xml == null) { - return null; - } - - try { - Validator validator = getValidator(version); - - if (validator == null) { - validatorFound[0] = Boolean.FALSE; - outError[0] = String.format( - "XML verification failed for %1$s.\nNo suitable XML Schema Validator could be found in your Java environment. Please consider updating your version of Java.", - url); - return null; - } - - validatorFound[0] = Boolean.TRUE; - - // Reset the stream if it supports that operation. - xml.reset(); - - // Validation throws a bunch of possible Exceptions on failure. - validator.validate(new StreamSource(xml)); - return SdkStatsConstants.getSchemaUri(version); - - } catch (SAXParseException e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nLine %2$d:%3$d, Error: %4$s", - url, - e.getLineNumber(), - e.getColumnNumber(), - e.toString()); - - } catch (Exception e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nError: %2$s", - url, - e.toString()); - } - return null; - } - - /** - * Helper method that returns a validator for our XSD, or null if the current Java - * implementation can't process XSD schemas. - * - * @param version The version of the XML Schema. - * See {@link SdkStatsConstants#getXsdStream(int)} - */ - private Validator getValidator(int version) throws SAXException { - InputStream xsdStream = SdkStatsConstants.getXsdStream(version); - try { - SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - - if (factory == null) { - return null; - } - - // This may throw a SAX Exception if the schema itself is not a valid XSD - Schema schema = factory.newSchema(new StreamSource(xsdStream)); - - Validator validator = schema == null ? null : schema.newValidator(); - - return validator; - } finally { - if (xsdStream != null) { - try { - xsdStream.close(); - } catch (IOException ignore) {} - } - } - } - - /** - * Takes an XML document as a string as parameter and returns a DOM for it. - * - * On error, returns null and prints a (hopefully) useful message on the monitor. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Document getDocument(InputStream xml, ITaskMonitor monitor) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(true); - factory.setNamespaceAware(true); - - DocumentBuilder builder = factory.newDocumentBuilder(); - xml.reset(); - Document doc = builder.parse(new InputSource(xml)); - - return doc; - } catch (ParserConfigurationException e) { - monitor.logError("Failed to create XML document builder"); - - } catch (SAXException e) { - monitor.logError("Failed to parse XML document"); - - } catch (IOException e) { - monitor.logError("Failed to read XML document"); - } - - return null; - } - - /** - * Parses all valid platforms found in the XML. - * Changes the stats array returned by {@link #getStats()} - * (also returns the value directly, useful for unit tests.) - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SparseArray parseStatsDocument( - Document doc, - String nsUri, - ITaskMonitor monitor) { - - String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (baseUrl != null) { - if (baseUrl.length() <= 0 || !baseUrl.endsWith("/")) { //$NON-NLS-1$ - baseUrl = null; - } - } - - SparseArray platforms = new SparseArray(); - int maxApi = 0; - - Node root = getFirstChild(doc, nsUri, SdkStatsConstants.NODE_SDK_STATS); - if (root != null) { - for (Node child = root.getFirstChild(); - child != null; - child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI()) && - child.getLocalName().equals(SdkStatsConstants.NODE_PLATFORM)) { - - try { - Node node = getFirstChild(child, nsUri, SdkStatsConstants.NODE_API_LEVEL); - int apiLevel = Integer.parseInt(node.getTextContent().trim()); - - if (apiLevel < 1) { - // bad API level, ignore it. - continue; - } - - if (platforms.indexOfKey(apiLevel) >= 0) { - // if we already loaded that API, ignore duplicates - continue; - } - - String codeName = - getFirstChild(child, nsUri, SdkStatsConstants.NODE_CODENAME). - getTextContent().trim(); - String versName = - getFirstChild(child, nsUri, SdkStatsConstants.NODE_VERSION). - getTextContent().trim(); - - if (codeName == null || versName == null || - codeName.isEmpty() || versName.isEmpty()) { - // bad names. ignore. - continue; - } - - node = getFirstChild(child, nsUri, SdkStatsConstants.NODE_SHARE); - float percent = Float.parseFloat(node.getTextContent().trim()); - - if (percent < 0 || percent > 100) { - // invalid percentage. ignore. - continue; - } - - PlatformStatBase p = new PlatformStatBase( - apiLevel, versName, codeName, percent); - platforms.put(apiLevel, p); - - maxApi = apiLevel > maxApi ? apiLevel : maxApi; - - } catch (Exception ignore) { - // Error parsing this platform. Ignore it. - continue; - } - } - } - } - - mStats.clear(); - - // Compute cumulative share percents & fill in final map - for (int api = 1; api <= maxApi; api++) { - PlatformStatBase p = platforms.get(api); - if (p == null) { - continue; - } - - float sum = p.getShare(); - for (int j = api + 1; j <= maxApi; j++) { - PlatformStatBase pj = platforms.get(j); - if (pj != null) { - sum += pj.getShare(); - } - } - - mStats.put(api, new PlatformStat(p, sum)); - } - - return mStats; - } - - /** - * Returns the first child element with the given XML local name. - * If xmlLocalName is null, returns the very first child element. - */ - private Node getFirstChild(Node node, String nsUri, String xmlLocalName) { - - for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI())) { - if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) { - return child; - } - } - } - - return null; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UrlOpener.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UrlOpener.java deleted file mode 100644 index 338463cb..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UrlOpener.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.utils.Pair; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.ProtocolVersion; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.AuthState; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.NTCredentials; -import org.apache.http.auth.params.AuthPNames; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.params.AuthPolicy; -import org.apache.http.client.protocol.ClientContext; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.ProxySelectorRoutePlanner; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.FileNotFoundException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.Proxy; -import java.net.ProxySelector; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -/** - * This class holds static methods for downloading URL resources. - * @see #openUrl(String, boolean, ITaskMonitor, Header[]) - *

- * Implementation detail: callers should use {@link DownloadCache} instead of this class. - * {@link DownloadCache#openDirectUrl} is a direct pass-through to {@link UrlOpener} since - * there's no caching. However from an implementation perspective it's still recommended - * to pass down a {@link DownloadCache} instance, which will let us override the implementation - * later on (for testing, for example.) - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -class UrlOpener { - - private static final boolean DEBUG = - System.getenv("ANDROID_DEBUG_URL_OPENER") != null; //$NON-NLS-1$ - - private static Map sRealmCache = - new HashMap(); - - /** Timeout to establish a connection, in milliseconds. */ - private static int sConnectionTimeoutMs; - /** Timeout waiting for data on a socket, in milliseconds. */ - private static int sSocketTimeoutMs; - - static { - if (DEBUG) { - Properties props = System.getProperties(); - for (String key : new String[] { - "http.proxyHost", //$NON-NLS-1$ - "http.proxyPort", //$NON-NLS-1$ - "https.proxyHost", //$NON-NLS-1$ - "https.proxyPort" }) { //$NON-NLS-1$ - String prop = props.getProperty(key); - if (prop != null) { - System.out.printf( - "SdkLib.UrlOpener Java.Prop %s='%s'\n", //$NON-NLS-1$ - key, prop); - } - } - } - - try { - sConnectionTimeoutMs = Integer.parseInt(System.getenv("ANDROID_SDKMAN_CONN_TIMEOUT")); - } catch (Exception ignore) { - sConnectionTimeoutMs = 2 * 60 * 1000; - } - - try { - sSocketTimeoutMs = Integer.parseInt(System.getenv("ANDROID_SDKMAN_READ_TIMEOUT")); - } catch (Exception ignore) { - sSocketTimeoutMs = 1 * 60 * 1000; - } - } - - /** - * This class cannot be instantiated. - * @see #openUrl(String, boolean, ITaskMonitor, Header[]) - */ - private UrlOpener() { - } - - /** - * Opens a URL. It can be a simple URL or one which requires basic - * authentication. - *

- * Tries to access the given URL. If http response is either - * {@code HttpStatus.SC_UNAUTHORIZED} or - * {@code HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED}, asks for - * login/password and tries to authenticate into proxy server and/or URL. - *

- * This implementation relies on the Apache Http Client due to its - * capabilities of proxy/http authentication.
- * Proxy configuration is determined by {@link ProxySelectorRoutePlanner} using the JVM proxy - * settings by default. - *

- * For more information see:
- * - {@code http://hc.apache.org/httpcomponents-client-ga/}
- * - {@code http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/ProxySelectorRoutePlanner.html} - *

- * There's a very simple realm cache implementation. - * Login/Password for each realm are stored in a static {@link Map}. - * Before asking the user the method verifies if the information is already - * available in the memory cache. - * - * @param url the URL string to be opened. - * @param needsMarkResetSupport Indicates the caller must have an input stream that - * supports the mark/reset operations (as indicated by {@link InputStream#markSupported()}. - * Implementation detail: If the original stream does not, it will be fetched and wrapped - * into a {@link ByteArrayInputStream}. This can only work sanely if the resource is a - * small file that can fit in memory. It also means the caller has no chance of showing - * a meaningful download progress. If unsure, callers should set this to false. - * @param monitor {@link ITaskMonitor} to output status. - * @param headers An optional array of HTTP headers to use in the GET request. - * @return Returns a {@link Pair} with {@code first} holding an {@link InputStream} - * and {@code second} holding an {@link HttpResponse}. - * The returned pair is never null and contains - * at least a code; for http requests that provide them the response - * also contains locale, headers and an status line. - * The input stream can be null, especially in case of error. - * The caller must only accept the stream if the response code is 200 or similar. - * @throws IOException Exception thrown when there are problems retrieving - * the URL or its content. - * @throws CanceledByUserException Exception thrown if the user cancels the - * authentication dialog. - */ - @NonNull - static Pair openUrl( - @NonNull String url, - boolean needsMarkResetSupport, - @NonNull ITaskMonitor monitor, - @Nullable Header[] headers) - throws IOException, CanceledByUserException { - - Exception fallbackOnJavaUrlConnect = null; - Pair result = null; - - try { - result = openWithHttpClient(url, monitor, headers); - - } catch (UnknownHostException e) { - // Host in unknown. No need to even retry with the Url object, - // if it's broken, it's broken. It's already an IOException but - // it could use a better message. - throw new IOException("Unknown Host " + e.getMessage(), e); - - } catch (ClientProtocolException e) { - // We get this when HttpClient fails to accept the current protocol, - // e.g. when processing file:// URLs. - fallbackOnJavaUrlConnect = e; - - } catch (IOException e) { - throw e; - - } catch (CanceledByUserException e) { - // HTTP Basic Auth or NTLM login was canceled by user. - throw e; - - } catch (Exception e) { - if (DEBUG) { - System.out.printf("[HttpClient Error] %s : %s\n", url, e.toString()); - } - - fallbackOnJavaUrlConnect = e; - } - - if (fallbackOnJavaUrlConnect != null) { - // If the protocol is not supported by HttpClient (e.g. file:///), - // revert to the standard java.net.Url.open. - - try { - result = openWithUrl(url, headers); - } catch (IOException e) { - throw e; - } catch (Exception e) { - if (DEBUG && !fallbackOnJavaUrlConnect.equals(e)) { - System.out.printf("[Url Error] %s : %s\n", url, e.toString()); - } - } - } - - // If the caller requires an InputStream that supports mark/reset, let's - // make sure we have such a stream. - if (result != null && needsMarkResetSupport) { - InputStream is = result.getFirst(); - if (is != null) { - if (!is.markSupported()) { - try { - // Consume the whole input stream and offer a byte array stream instead. - // This can only work sanely if the resource is a small file that can - // fit in memory. It also means the caller has no chance of showing - // a meaningful download progress. - InputStream is2 = toByteArrayInputStream(is); - if (is2 != null) { - result = Pair.of(is2, result.getSecond()); - try { - is.close(); - } catch (Exception ignore) {} - } - } catch (Exception e3) { - // Ignore. If this can't work, caller will fail later. - } - } - } - } - - if (result == null) { - // Make up an error code if we don't have one already. - HttpResponse outResponse = new BasicHttpResponse( - new ProtocolVersion("HTTP", 1, 0), //$NON-NLS-1$ - HttpStatus.SC_METHOD_FAILURE, ""); //$NON-NLS-1$; // 420=Method Failure - result = Pair.of(null, outResponse); - } - - return result; - } - - // ByteArrayInputStream is the duct tape of input streams. - private static InputStream toByteArrayInputStream(InputStream is) throws IOException { - int inc = 4096; - int curr = 0; - byte[] result = new byte[inc]; - - int n; - while ((n = is.read(result, curr, result.length - curr)) != -1) { - curr += n; - if (curr == result.length) { - byte[] temp = new byte[curr + inc]; - System.arraycopy(result, 0, temp, 0, curr); - result = temp; - } - } - - return new ByteArrayInputStream(result, 0, curr); - } - - private static Pair openWithUrl( - String url, - Header[] inHeaders) throws IOException { - URL u = new URL(url); - - URLConnection c = u.openConnection(); - - c.setConnectTimeout(sConnectionTimeoutMs); - c.setReadTimeout(sSocketTimeoutMs); - - if (inHeaders != null) { - for (Header header : inHeaders) { - c.setRequestProperty(header.getName(), header.getValue()); - } - } - - // Trigger the access to the resource - // (at which point setRequestProperty can't be used anymore.) - int code = 200; - - if (c instanceof HttpURLConnection) { - code = ((HttpURLConnection) c).getResponseCode(); - } - - // Get the input stream. That can fail for a file:// that doesn't exist - // in which case we set the response code to 404. - // Also we need a buffered input stream since the caller need to use is.reset(). - InputStream is = null; - try { - is = new BufferedInputStream(c.getInputStream()); - } catch (Exception ignore) { - if (is == null && code == 200) { - code = 404; - } - } - - HttpResponse outResponse = new BasicHttpResponse( - new ProtocolVersion(u.getProtocol(), 1, 0), // make up the protocol version - code, ""); //$NON-NLS-1$; - - Map> outHeaderMap = c.getHeaderFields(); - - for (Entry> entry : outHeaderMap.entrySet()) { - String name = entry.getKey(); - if (name != null) { - List values = entry.getValue(); - if (!values.isEmpty()) { - outResponse.setHeader(name, values.get(0)); - } - } - } - - return Pair.of(is, outResponse); - } - - @NonNull - private static Pair openWithHttpClient( - @NonNull String url, - @NonNull ITaskMonitor monitor, - Header[] inHeaders) - throws IOException, ClientProtocolException, CanceledByUserException { - UserCredentials result = null; - String realm = null; - - HttpParams params = new BasicHttpParams(); - HttpConnectionParams.setConnectionTimeout(params, sConnectionTimeoutMs); - HttpConnectionParams.setSoTimeout(params, sSocketTimeoutMs); - - // use the simple one - final DefaultHttpClient httpClient = new DefaultHttpClient(params); - - - // create local execution context - HttpContext localContext = new BasicHttpContext(); - final HttpGet httpGet = new HttpGet(url); - if (inHeaders != null) { - for (Header header : inHeaders) { - httpGet.addHeader(header); - } - } - - // retrieve local java configured network in case there is the need to - // authenticate a proxy - ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner( - httpClient.getConnectionManager().getSchemeRegistry(), - ProxySelector.getDefault()); - httpClient.setRoutePlanner(routePlanner); - - // Set preference order for authentication options. - // In particular, we don't add AuthPolicy.SPNEGO, which is given preference over NTLM in - // servers that support both, as it is more secure. However, we don't seem to handle it - // very well, so we leave it off the list. - // See http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html for - // more info. - List authpref = new ArrayList(); - authpref.add(AuthPolicy.BASIC); - authpref.add(AuthPolicy.DIGEST); - authpref.add(AuthPolicy.NTLM); - httpClient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref); - httpClient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref); - - if (DEBUG) { - try { - URI uri = new URI(url); - ProxySelector sel = routePlanner.getProxySelector(); - if (sel != null && uri.getScheme().startsWith("httP")) { //$NON-NLS-1$ - List list = sel.select(uri); - System.out.printf( - "SdkLib.UrlOpener:\n Connect to: %s\n Proxy List: %s\n", //$NON-NLS-1$ - url, - list == null ? "(null)" : Arrays.toString(list.toArray()));//$NON-NLS-1$ - } - } catch (Exception e) { - System.out.printf( - "SdkLib.UrlOpener: Failed to get proxy info for %s: %s\n", //$NON-NLS-1$ - url, e.toString()); - } - } - - boolean trying = true; - // loop while the response is being fetched - while (trying) { - // connect and get status code - HttpResponse response = httpClient.execute(httpGet, localContext); - int statusCode = response.getStatusLine().getStatusCode(); - - if (DEBUG) { - System.out.printf(" Status: %d\n", statusCode); //$NON-NLS-1$ - } - - // check whether any authentication is required - AuthState authenticationState = null; - if (statusCode == HttpStatus.SC_UNAUTHORIZED) { - // Target host authentication required - authenticationState = (AuthState) localContext - .getAttribute(ClientContext.TARGET_AUTH_STATE); - } - if (statusCode == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { - // Proxy authentication required - authenticationState = (AuthState) localContext - .getAttribute(ClientContext.PROXY_AUTH_STATE); - } - if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NOT_MODIFIED) { - // in case the status is OK and there is a realm and result, - // cache it - if (realm != null && result != null) { - sRealmCache.put(realm, result); - } - } - - // there is the need for authentication - if (authenticationState != null) { - - // get scope and realm - AuthScope authScope = authenticationState.getAuthScope(); - - // If the current realm is different from the last one it means - // a pass was performed successfully to the last URL, therefore - // cache the last realm - if (realm != null && !realm.equals(authScope.getRealm())) { - sRealmCache.put(realm, result); - } - - realm = authScope.getRealm(); - - // in case there is cache for this Realm, use it to authenticate - if (sRealmCache.containsKey(realm)) { - result = sRealmCache.get(realm); - } else { - // since there is no cache, request for login and password - result = monitor.displayLoginCredentialsPrompt("Site Authentication", - "Please login to the following domain: " + realm + - "\n\nServer requiring authentication:\n" + authScope.getHost()); - if (result == null) { - throw new CanceledByUserException("User canceled login dialog."); - } - } - - // retrieve authentication data - String user = result.getUserName(); - String password = result.getPassword(); - String workstation = result.getWorkstation(); - String domain = result.getDomain(); - - // proceed in case there is indeed a user - if (user != null && !user.isEmpty()) { - Credentials credentials = new NTCredentials(user, password, - workstation, domain); - httpClient.getCredentialsProvider().setCredentials(authScope, credentials); - trying = true; - } else { - trying = false; - } - } else { - trying = false; - } - - HttpEntity entity = response.getEntity(); - - if (entity != null) { - if (trying) { - // in case another pass to the Http Client will be performed, close the entity. - entity.getContent().close(); - } else { - // since no pass to the Http Client is needed, retrieve the - // entity's content. - - // Note: don't use something like a BufferedHttpEntity since it would consume - // all content and store it in memory, resulting in an OutOfMemory exception - // on a large download. - InputStream is = new FilterInputStream(entity.getContent()) { - @Override - public void close() throws IOException { - // Since Http Client is no longer needed, close it. - - // Bug #21167: we need to tell http client to shutdown - // first, otherwise the super.close() would continue - // downloading and not return till complete. - - httpClient.getConnectionManager().shutdown(); - super.close(); - } - }; - - HttpResponse outResponse = new BasicHttpResponse(response.getStatusLine()); - outResponse.setHeaders(response.getAllHeaders()); - outResponse.setLocale(response.getLocale()); - - return Pair.of(is, outResponse); - } - } else if (statusCode == HttpStatus.SC_NOT_MODIFIED) { - // It's ok to not have an entity (e.g. nothing to download) for a 304 - HttpResponse outResponse = new BasicHttpResponse(response.getStatusLine()); - outResponse.setHeaders(response.getAllHeaders()); - outResponse.setLocale(response.getLocale()); - - return Pair.of(null, outResponse); - } - } - - // We get here if we did not succeed. Callers do not expect a null result. - httpClient.getConnectionManager().shutdown(); - throw new FileNotFoundException(url); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java deleted file mode 100644 index e4401de0..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2014 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.internal.repository.archives; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.NoPreviewRevision; - -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ArchFilter { - - private static final String PROP_HOST_OS = "Archive.HostOs"; //$NON-NLS-1$ - private static final String PROP_HOST_BITS = "Archive.HostBits"; //$NON-NLS-1$ - private static final String PROP_JVM_BITS = "Archive.JvmBits"; //$NON-NLS-1$ - private static final String PROP_MIN_JVM_VERSION = "Archive.MinJvmVers"; //$NON-NLS-1$ - - /** - * The legacy property used to serialize {@link LegacyOs} in source.properties files. - *

- * Replaced by {@code ArchFilter.PROP_HOST_OS}. - */ - public static final String LEGACY_PROP_OS = "Archive.Os"; //$NON-NLS-1$ - - /** - * The legacy property used to serialize {@link LegacyArch} in source.properties files. - *

- * Replaced by {@code ArchFilter.PROP_HOST_BITS} and {@code ArchFilter.PROP_JVM_BITS}. - */ - public static final String LEGACY_PROP_ARCH = "Archive.Arch"; //$NON-NLS-1$ - - private final HostOs mHostOs; - private final BitSize mHostBits; - private final BitSize mJvmBits; - private final NoPreviewRevision mMinJvmVersion; - - /** - * Creates a new {@link ArchFilter} with the specified filter attributes. - *

- * This filters represents the attributes requires for a package's {@link Archive} to - * be installable on the current architecture. Not all fields are required -- those that - * are not specified imply there is no limitation on that particular attribute. - * - * - * @param hostOs The host OS or null if there's no limitation for this package. - * @param hostBits The host bit size or null if there's no limitation for this package. - * @param jvmBits The JVM bit size or null if there's no limitation for this package. - * @param minJvmVersion The minimal JVM version required by this package - * or null if there's no limitation for this package. - */ - public ArchFilter(@Nullable HostOs hostOs, - @Nullable BitSize hostBits, - @Nullable BitSize jvmBits, - @Nullable NoPreviewRevision minJvmVersion) { - mHostOs = hostOs; - mHostBits = hostBits; - mJvmBits = jvmBits; - mMinJvmVersion = minJvmVersion; - } - - /** - * Creates an {@link ArchFilter} using properties previously saved in a {@link Properties} - * object, typically by the {@link ArchFilter#saveProperties(Properties)} method. - *

- * Missing properties are set to null and will not filter. - * - * @param props A properties object previously filled by {@link #saveProperties(Properties)}. - * If null, a default empty {@link ArchFilter} is created. - */ - public ArchFilter(@Nullable Properties props) { - HostOs hostOs = null; - BitSize hostBits = null; - BitSize jvmBits = null; - NoPreviewRevision minJvmVers = null; - - if (props != null) { - hostOs = HostOs .fromXmlName(props.getProperty(PROP_HOST_OS)); - hostBits = BitSize.fromXmlName(props.getProperty(PROP_HOST_BITS)); - jvmBits = BitSize.fromXmlName(props.getProperty(PROP_JVM_BITS)); - - try { - minJvmVers = NoPreviewRevision.parseRevision(props.getProperty(PROP_MIN_JVM_VERSION)); - } catch (NumberFormatException ignore) {} - - // Backward compatibility with older PROP_OS and PROP_ARCH values - if (!props.containsKey(PROP_HOST_OS) && props.containsKey(LEGACY_PROP_OS)) { - hostOs = HostOs.fromXmlName(props.getProperty(LEGACY_PROP_OS)); - } - if (!props.containsKey(PROP_HOST_BITS) && - !props.containsKey(PROP_HOST_BITS) && - props.containsKey(LEGACY_PROP_ARCH)) { - // We'll only handle the typical x86 and x86_64 values of the old PROP_ARCH - // value and ignore the PPC value. "Any" is equivalent to keeping the new - // attributes to null. - String v = props.getProperty(LEGACY_PROP_ARCH).toLowerCase(); - - if (v.indexOf("x86_64") > 0) { - // JVM in 64-bit x86_64 mode so host-bits should be 64 too. - hostBits = jvmBits = BitSize._64; - } else if (v.indexOf("x86") > 0) { - // JVM in 32-bit x86 mode, but host-bits could be either 32 or 64 - // so we don't set this one. - jvmBits = BitSize._32; - } - } - } - - mHostOs = hostOs; - mHostBits = hostBits; - mJvmBits = jvmBits; - mMinJvmVersion = minJvmVers; - } - - /** @return the host OS or null if there's no limitation for this package. */ - @Nullable - public HostOs getHostOS() { - return mHostOs; - } - - /** @return the host bit size or null if there's no limitation for this package. */ - @Nullable - public BitSize getHostBits() { - return mHostBits; - } - - /** @return the JVM bit size or null if there's no limitation for this package. */ - @Nullable - public BitSize getJvmBits() { - return mJvmBits; - } - - /** @return the minimal JVM version required by this package - * or null if there's no limitation for this package. */ - @Nullable - public NoPreviewRevision getMinJvmVersion() { - return mMinJvmVersion; - } - - /** - * Checks whether {@code this} {@link ArchFilter} is compatible with the right-hand side one. - *

- * Typically this is used to check whether "this downloaded package is compatible with the - * current architecture", which would be expressed as: - *

-     * DownloadedArchive.filter.isCompatibleWith(ArhFilter.getCurrent())
-     * 
- * For the host OS & bit size attribute, if the attributes are non-null they must be equal. - * For the min-jvm-version, "this" version (the package we want to install) needs to be lower - * or equal to the "required" (current host) version. - * - * @param required The requirements to meet. - * @return True if this filter meets or exceeds the given requirements. - */ - public boolean isCompatibleWith(@NonNull ArchFilter required) { - if (mHostOs != null - && required.mHostOs != null - && !mHostOs.equals(required.mHostOs)) { - return false; - } - - if (mHostBits != null - && required.mHostBits != null - && !mHostBits.equals(required.mHostBits)) { - return false; - } - - if (mJvmBits != null - && required.mJvmBits != null - && !mJvmBits.equals(required.mJvmBits)) { - return false; - } - - if (mMinJvmVersion != null - && required.mMinJvmVersion != null - && mMinJvmVersion.compareTo(required.mMinJvmVersion) > 0) { - return false; - } - - return true; - } - - /** - * Returns an {@link ArchFilter} that represents the current host platform. - * @return an {@link ArchFilter} that represents the current host platform. - */ - @NonNull - public static ArchFilter getCurrent() { - String os = System.getProperty("os.name"); //$NON-NLS-1$ - HostOs hostOS = null; - if (os.startsWith("Mac")) { //$NON-NLS-1$ - hostOS = HostOs.MACOSX; - } else if (os.startsWith("Windows")) { //$NON-NLS-1$ - hostOS = HostOs.WINDOWS; - } else if (os.startsWith("Linux")) { //$NON-NLS-1$ - hostOS = HostOs.LINUX; - } - - BitSize jvmBits; - String arch = System.getProperty("os.arch"); //$NON-NLS-1$ - - if (arch.equalsIgnoreCase("x86_64") || //$NON-NLS-1$ - arch.equalsIgnoreCase("ia64") || //$NON-NLS-1$ - arch.equalsIgnoreCase("amd64")) { //$NON-NLS-1$ - jvmBits = BitSize._64; - } else { - jvmBits = BitSize._32; - } - - // TODO figure out the host bit size. - // When jvmBits is 64 we know it's surely 64 - // but that's not necessarily obvious when jvmBits is 32. - BitSize hostBits = jvmBits; - - NoPreviewRevision minJvmVersion = null; - String javav = System.getProperty("java.version"); //$NON-NLS-1$ - // java Version is typically in the form "1.2.3_45" and we just need to keep up to "1.2.3" - // since our revision numbers are in 3-parts form (1.2.3). - Pattern p = Pattern.compile("((\\d+)(\\.\\d+)?(\\.\\d+)?).*"); //$NON-NLS-1$ - Matcher m = p.matcher(javav); - if (m.matches()) { - minJvmVersion = NoPreviewRevision.parseRevision(m.group(1)); - } - - return new ArchFilter(hostOS, hostBits, jvmBits, minJvmVersion); - } - - /** - * Save this {@link ArchFilter} attributes into the the given {@link Properties} object. - * These properties can later be given to the constructor that takes a {@link Properties} object. - *

- * Null attributes are not saved in the properties. - * - * @param props A non-null properties object to fill with non-null attributes. - */ - void saveProperties(@NonNull Properties props) { - if (mHostOs != null) { - props.setProperty(PROP_HOST_OS, mHostOs.getXmlName()); - } - if (mHostBits != null) { - props.setProperty(PROP_HOST_BITS, mHostBits.getXmlName()); - } - if (mJvmBits != null) { - props.setProperty(PROP_JVM_BITS, mJvmBits.getXmlName()); - } - if (mMinJvmVersion != null) { - props.setProperty(PROP_MIN_JVM_VERSION, mMinJvmVersion.toShortString()); - } - } - - /** String for debug purposes. */ - @Override - public String toString() { - return ""; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mHostOs == null) ? 0 : mHostOs.hashCode()); - result = prime * result + ((mHostBits == null) ? 0 : mHostBits.hashCode()); - result = prime * result + ((mJvmBits == null) ? 0 : mJvmBits.hashCode()); - result = prime * result + ((mMinJvmVersion == null) ? 0 : mMinJvmVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ArchFilter other = (ArchFilter) obj; - if (mHostBits != other.mHostBits) { - return false; - } - if (mHostOs != other.mHostOs) { - return false; - } - if (mJvmBits != other.mJvmBits) { - return false; - } - if (mMinJvmVersion == null) { - if (other.mMinJvmVersion != null) { - return false; - } - } else if (!mMinJvmVersion.equals(other.mMinJvmVersion)) { - return false; - } - return true; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/Archive.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/Archive.java deleted file mode 100644 index 69ed686c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/Archive.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.archives; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.io.LegacyFileOp; - -import java.io.File; -import java.util.Properties; - - -/** - * A {@link Archive} is the base class for "something" that can be downloaded from - * the SDK repository. - *

- * A package has some attributes (revision, description) and a list of archives - * which represent the downloadable bits. - *

- * Packages are offered by a {@link SdkSource} (a download site). - * The {@link ArchiveInstaller} takes care of downloading, unpacking and installing an archive. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. -*/ -@Deprecated -public class Archive implements IDescription, Comparable { - - private final String mUrl; - private final long mSize; - private final String mChecksum; - private final ChecksumType mChecksumType = ChecksumType.SHA1; - private final Package mPackage; - private final String mLocalOsPath; - private final boolean mIsLocal; - private final ArchFilter mArchFilter; - - /** - * Creates a new remote archive. - * This is typically called when inflating a remote-package info from XML meta-data. - * - * @param pkg The package that contains this archive. Typically not null. - * @param archFilter The {@link ArchFilter} for the archive. Typically not null. - * @param url The URL where the archive is available. - * Typically not null but code should be able to handles both. - * @param size The expected size in bytes of the archive to download. - * @param checksum The expected checksum string of the archive. Currently only the - * {@link ChecksumType#SHA1} format is supported. - */ - public Archive(@Nullable Package pkg, - @Nullable ArchFilter archFilter, - @Nullable String url, - long size, - @NonNull String checksum) { - mPackage = pkg; - mArchFilter = archFilter != null ? archFilter : new ArchFilter(null); - mUrl = url == null ? null : url.trim(); - mLocalOsPath = null; - mSize = size; - mChecksum = checksum; - mIsLocal = false; - } - - /** - * Creates a new local archive. - * This is typically called when inflating a local-package info by reading a local - * source.properties file. In this case a few properties like the URL, checksum and - * size are not defined. - * - * @param pkg The package that contains this archive. Cannot be null. - * @param props A set of properties. Can be null. - * @param localOsPath The OS path where the archive is installed if this represents a - * local package. Null for a remote package. - */ - @VisibleForTesting(visibility=Visibility.PACKAGE) - public Archive(@NonNull Package pkg, - @Nullable Properties props, - @Nullable String localOsPath) { - mPackage = pkg; - mArchFilter = new ArchFilter(props); - mUrl = null; - mLocalOsPath = localOsPath; - mSize = 0; - mChecksum = ""; - mIsLocal = localOsPath != null; - } - - /** - * Save the properties of the current archive in the give {@link Properties} object. - * These properties will later be give the constructor that takes a {@link Properties} object. - */ - void saveProperties(@NonNull Properties props) { - mArchFilter.saveProperties(props); - } - - /** - * Returns true if this is a locally installed archive. - * Returns false if this is a remote archive that needs to be downloaded. - */ - public boolean isLocal() { - return mIsLocal; - } - - /** - * Returns the package that created and owns this archive. - * It should generally not be null. - */ - @Nullable - public Package getParentPackage() { - return mPackage; - } - - /** - * Returns the archive size, an int > 0. - * Size will be 0 if this a local installed folder of unknown size. - */ - public long getSize() { - return mSize; - } - - /** - * Returns the SHA1 archive checksum, as a 40-char hex. - * Can be empty but not null for local installed folders. - */ - @NonNull - public String getChecksum() { - return mChecksum; - } - - /** - * Returns the checksum type, always {@link ChecksumType#SHA1} right now. - */ - @NonNull - public ChecksumType getChecksumType() { - return mChecksumType; - } - - /** - * Returns the download archive URL, either absolute or relative to the repository xml. - * Always return null for a local installed folder. - * @see #getLocalOsPath() - */ - @Nullable - public String getUrl() { - return mUrl; - } - - /** - * Returns the local OS folder where a local archive is installed. - * Always return null for remote archives. - * @see #getUrl() - */ - @Nullable - public String getLocalOsPath() { - return mLocalOsPath; - } - - /** - * Returns the architecture filter. - * This non-null filter indicates which host/jvm this archive is compatible with. - */ - @NonNull - public ArchFilter getArchFilter() { - return mArchFilter; - } - - /** - * Generates a description of the {@link ArchFilter} supported by this archive. - */ - public String getOsDescription() { - StringBuilder sb = new StringBuilder(); - - HostOs hos = mArchFilter.getHostOS(); - sb.append(hos == null ? "any OS" : hos.getUiName()); - - BitSize jvmBits = mArchFilter.getJvmBits(); - if (jvmBits != null) { - sb.append(", JVM ").append(jvmBits.getSize()).append("-bits"); - } - - BitSize hostBits = mArchFilter.getJvmBits(); - if (hostBits != null) { - sb.append(", Host ").append(hostBits.getSize()).append("-bits"); - } - - return sb.toString(); - } - - /** - * Returns the short description of the source, if not null. - * Otherwise returns the default Object toString result. - *

- * This is mostly helpful for debugging. - * For UI display, use the {@link IDescription} interface. - */ - @Override - public String toString() { - String s = getShortDescription(); - if (s != null) { - return s; - } - return super.toString(); - } - - /** - * Generates a short description for this archive. - */ - @Override - public String getShortDescription() { - return String.format("Archive for %1$s", getOsDescription()); - } - - /** - * Generates a longer description for this archive. - */ - @Override - public String getLongDescription() { - return String.format("%1$s\n%2$s\n%3$s", - getShortDescription(), - getSizeDescription(), - getSha1Description()); - } - - public String getSizeDescription() { - long size = getSize(); - String sizeStr; - if (size < 1024) { - sizeStr = String.format("%d Bytes", size); - } else if (size < 1024 * 1024) { - sizeStr = String.format("%d KiB", Math.round(size / 1024.0)); - } else if (size < 1024 * 1024 * 1024) { - sizeStr = String.format("%.1f MiB", - Math.round(10.0 * size / (1024 * 1024.0))/ 10.0); - } else { - sizeStr = String.format("%.1f GiB", - Math.round(10.0 * size / (1024 * 1024 * 1024.0))/ 10.0); - } - - return String.format("Size: %1$s", sizeStr); - } - - public String getSha1Description() { - return String.format("SHA1: %1$s", getChecksum()); - } - - /** - * Returns true if this archive can be installed on the current platform. - */ - public boolean isCompatible() { - ArchFilter current = ArchFilter.getCurrent(); - return mArchFilter.isCompatibleWith(current); - } - - /** - * Delete the archive folder if this is a local archive. - */ - public void deleteLocal() { - if (isLocal()) { - new LegacyFileOp().deleteFileOrFolder(new File(getLocalOsPath())); - } - } - - /** - * Archives are compared using their {@link Package} ordering. - * - * @see Package#compareTo(Package) - */ - @Override - public int compareTo(Archive rhs) { - if (mPackage != null && rhs != null) { - return mPackage.compareTo(rhs.getParentPackage()); - } - return 0; - } - - /** - * Note: An {@link Archive}'s hash code does NOT depend on the parent {@link Package} hash code. - *

- * {@inheritDoc} - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mArchFilter == null) ? 0 : mArchFilter.hashCode()); - result = prime * result + ((mChecksum == null) ? 0 : mChecksum.hashCode()); - result = prime * result + ((mChecksumType == null) ? 0 : mChecksumType.hashCode()); - result = prime * result + (mIsLocal ? 1231 : 1237); - result = prime * result + ((mLocalOsPath == null) ? 0 : mLocalOsPath.hashCode()); - result = prime * result + (int) (mSize ^ (mSize >>> 32)); - result = prime * result + ((mUrl == null) ? 0 : mUrl.hashCode()); - return result; - } - - /** - * Note: An {@link Archive}'s equality does NOT depend on the parent {@link Package} equality. - *

- * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof Archive)) { - return false; - } - Archive other = (Archive) obj; - if (mArchFilter == null) { - if (other.mArchFilter != null) { - return false; - } - } else if (!mArchFilter.equals(other.mArchFilter)) { - return false; - } - if (mChecksum == null) { - if (other.mChecksum != null) { - return false; - } - } else if (!mChecksum.equals(other.mChecksum)) { - return false; - } - if (mChecksumType == null) { - if (other.mChecksumType != null) { - return false; - } - } else if (!mChecksumType.equals(other.mChecksumType)) { - return false; - } - if (mIsLocal != other.mIsLocal) { - return false; - } - if (mLocalOsPath == null) { - if (other.mLocalOsPath != null) { - return false; - } - } else if (!mLocalOsPath.equals(other.mLocalOsPath)) { - return false; - } - if (mSize != other.mSize) { - return false; - } - if (mUrl == null) { - if (other.mUrl != null) { - return false; - } - } else if (!mUrl.equals(other.mUrl)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveInstaller.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveInstaller.java deleted file mode 100644 index 7a34385e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveInstaller.java +++ /dev/null @@ -1,1220 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.archives; - -import com.android.SdkConstants; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.CanceledByUserException; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.RepoConstants; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; -import com.android.utils.Pair; - -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipFile; -import org.apache.http.Header; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.message.BasicHeader; - -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.Set; -import java.util.TreeSet; -import java.util.regex.Pattern; - -/** - * Performs the work of installing a given {@link Archive}. - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ArchiveInstaller { - - private static final String PROP_STATUS_CODE = "StatusCode"; //$NON-NLS-1$ - public static final String ENV_VAR_IGNORE_COMPAT = "ANDROID_SDK_IGNORE_COMPAT"; //$NON-NLS-1$ - - public static final int NUM_MONITOR_INC = 100; - - /** The current {@link LegacyFileOp} to use. Never null. */ - private final IFileOp mFileOp; - - /** - * Generates an {@link ArchiveInstaller} that relies on the default {@link LegacyFileOp}. - */ - public ArchiveInstaller() { - mFileOp = new LegacyFileOp(); - } - - /** - * Generates an {@link ArchiveInstaller} that relies on the given {@link LegacyFileOp}. - * - * @param fileUtils An alternate version of {@link LegacyFileOp} to use for file operations. - */ - protected ArchiveInstaller(IFileOp fileUtils) { - mFileOp = fileUtils; - } - - /** Returns current {@link LegacyFileOp} to use. Never null. */ - protected IFileOp getFileOp() { - return mFileOp; - } - - /** - * Install this {@link ArchiveReplacement}s. - * A "replacement" is composed of the actual new archive to install - * (c.f. {@link ArchiveReplacement#getNewArchive()} and an optional - * archive being replaced (c.f. {@link ArchiveReplacement#getReplaced()}. - * In the case of a new install, the later should be null. - *

- * The new archive to install will be skipped if it is incompatible. - * - * @return True if the archive was installed, false otherwise. - */ - public boolean install(ArchiveReplacement archiveInfo, - String osSdkRoot, - boolean forceHttp, - SdkManager sdkManager, - DownloadCache cache, - ITaskMonitor monitor) { - - Archive newArchive = archiveInfo.getNewArchive(); - Package pkg = newArchive.getParentPackage(); - - String name = pkg.getShortDescription(); - - if (newArchive.isLocal()) { - // This should never happen. - monitor.log("Skipping already installed archive: %1$s for %2$s", - name, - newArchive.getOsDescription()); - return false; - } - - // In detail mode, give us a way to force install of incompatible archives. - boolean checkIsCompatible = System.getenv(ENV_VAR_IGNORE_COMPAT) == null; - - if (checkIsCompatible && !newArchive.isCompatible()) { - monitor.log("Skipping incompatible archive: %1$s for %2$s", - name, - newArchive.getOsDescription()); - return false; - } - - Pair files = downloadFile(newArchive, osSdkRoot, cache, monitor, forceHttp); - File tmpFile = files == null ? null : files.getFirst(); - File propsFile = files == null ? null : files.getSecond(); - if (tmpFile != null) { - // Unarchive calls the pre/postInstallHook methods. - if (unarchive(archiveInfo, osSdkRoot, tmpFile, sdkManager, monitor)) { - monitor.log("Installed %1$s", name); - // Delete the temp archive if it exists, only on success - mFileOp.deleteFileOrFolder(tmpFile); - mFileOp.deleteFileOrFolder(propsFile); - return true; - } - } - - return false; - } - - /** - * Downloads an archive and returns the temp file with it. - * Caller is responsible with deleting the temp file when done. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Pair downloadFile(Archive archive, - String osSdkRoot, - DownloadCache cache, - ITaskMonitor monitor, - boolean forceHttp) { - - String pkgName = archive.getParentPackage().getShortDescription(); - monitor.setDescription("Downloading %1$s", pkgName); - monitor.log("Downloading %1$s", pkgName); - - String link = archive.getUrl(); - if (!link.startsWith("http://") //$NON-NLS-1$ - && !link.startsWith("https://") //$NON-NLS-1$ - && !link.startsWith("ftp://")) { //$NON-NLS-1$ - // Make the URL absolute by prepending the source - Package pkg = archive.getParentPackage(); - SdkSource src = pkg.getParentSource(); - if (src == null) { - monitor.logError("Internal error: no source for archive %1$s", pkgName); - return null; - } - - // take the URL to the repository.xml and remove the last component - // to get the base - String repoXml = src.getUrl(); - int pos = repoXml.lastIndexOf('/'); - String base = repoXml.substring(0, pos + 1); - - link = base + link; - } - - if (forceHttp) { - link = link.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Get the basename of the file we're downloading, i.e. the last component - // of the URL - int pos = link.lastIndexOf('/'); - String base = link.substring(pos + 1); - - // Rather than create a real temp file in the system, we simply use our - // temp folder (in the SDK base folder) and use the archive name for the - // download. This allows us to reuse or continue downloads. - - File tmpFolder = getTempFolder(osSdkRoot); - if (!mFileOp.isDirectory(tmpFolder)) { - if (mFileOp.isFile(tmpFolder)) { - mFileOp.deleteFileOrFolder(tmpFolder); - } - if (!mFileOp.mkdirs(tmpFolder)) { - monitor.logError("Failed to create directory %1$s", tmpFolder.getPath()); - return null; - } - } - File tmpFile = new File(tmpFolder, base); - - // property file were we'll keep partial/resume information for reuse. - File propsFile = new File(tmpFolder, base + ".inf"); //$NON-NLS-1$ - - // if the file exists, check its checksum & size. Use it if complete - if (mFileOp.exists(tmpFile)) { - if (mFileOp.length(tmpFile) == archive.getSize()) { - String chksum = ""; //$NON-NLS-1$ - try { - chksum = fileChecksum(archive.getChecksumType().getMessageDigest(), - tmpFile, - monitor); - } catch (NoSuchAlgorithmException e) { - // Ignore. - } - if (chksum.equalsIgnoreCase(archive.getChecksum())) { - // File is good, let's use it. - return Pair.of(tmpFile, propsFile); - } else { - // The file has the right size but the wrong content. - // Just remove it and this will trigger a full download below. - mFileOp.deleteFileOrFolder(tmpFile); - } - } - } - - Header[] resumeHeaders = preparePartialDownload(archive, tmpFile, propsFile); - - if (fetchUrl(archive, resumeHeaders, tmpFile, propsFile, link, pkgName, cache, monitor)) { - // Fetching was successful, let's use this file. - return Pair.of(tmpFile, propsFile); - } - return null; - } - - /** - * Prepares to do a partial/resume download. - * - * @param archive The archive we're trying to download. - * @param tmpFile The destination file to download (e.g. something.zip) - * @param propsFile A properties file generated by the last partial download (e.g. .zip.inf) - * @return Null in case we should perform a full download, or a set of headers - * to resume a partial download. - */ - private Header[] preparePartialDownload(Archive archive, File tmpFile, File propsFile) { - // We need both the destination file and its properties to do a resume. - if (mFileOp.isFile(tmpFile) && mFileOp.isFile(propsFile)) { - // The caller already checked the case were the destination file has the - // right size _and_ checksum, so we know at this point one of them is wrong - // here. - // We can obviously only resume a file if its size is smaller than expected. - if (mFileOp.length(tmpFile) < archive.getSize()) { - Properties props = mFileOp.loadProperties(propsFile); - - List

headers = new ArrayList
(2); - headers.add(new BasicHeader(HttpHeaders.RANGE, - String.format("bytes=%d-", mFileOp.length(tmpFile)))); - - // Don't use the properties if there's not at least a 200 or 206 code from - // the last download. - int status = 0; - try { - status = Integer.parseInt(props.getProperty(PROP_STATUS_CODE)); - } catch (Exception ignore) {} - - if (status == HttpStatus.SC_OK || status == HttpStatus.SC_PARTIAL_CONTENT) { - // Do we have an ETag and/or a Last-Modified? - String etag = props.getProperty(HttpHeaders.ETAG); - String lastMod = props.getProperty(HttpHeaders.LAST_MODIFIED); - - if (etag != null && !etag.isEmpty()) { - headers.add(new BasicHeader(HttpHeaders.IF_MATCH, etag)); - } else if (lastMod != null && !lastMod.isEmpty()) { - headers.add(new BasicHeader(HttpHeaders.IF_MATCH, lastMod)); - } - - return headers.toArray(new Header[headers.size()]); - } - } - } - - // Existing file is either of different size or content. - // Remove the existing file and request a full download. - mFileOp.deleteFileOrFolder(tmpFile); - mFileOp.deleteFileOrFolder(propsFile); - - return null; - } - - /** - * Computes the SHA-1 checksum of the content of the given file. - * Returns an empty string on error (rather than null). - */ - private String fileChecksum(MessageDigest digester, File tmpFile, ITaskMonitor monitor) { - InputStream is = null; - try { - is = new FileInputStream(tmpFile); - - byte[] buf = new byte[65536]; - int n; - - while ((n = is.read(buf)) >= 0) { - if (n > 0) { - digester.update(buf, 0, n); - } - } - - return getDigestChecksum(digester); - - } catch (FileNotFoundException e) { - // The FNF message is just the URL. Make it a bit more useful. - monitor.logError("File not found: %1$s", e.getMessage()); - - } catch (Exception e) { - monitor.logError("%1$s", e.getMessage()); //$NON-NLS-1$ - - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // pass - } - } - } - - return ""; //$NON-NLS-1$ - } - - /** - * Returns the SHA-1 from a {@link MessageDigest} as an hex string - * that can be compared with {@link Archive#getChecksum()}. - */ - private String getDigestChecksum(MessageDigest digester) { - int n; - // Create an hex string from the digest - byte[] digest = digester.digest(); - n = digest.length; - String hex = "0123456789abcdef"; //$NON-NLS-1$ - char[] hexDigest = new char[n * 2]; - for (int i = 0; i < n; i++) { - int b = digest[i] & 0x0FF; - hexDigest[i*2 + 0] = hex.charAt(b >>> 4); - hexDigest[i*2 + 1] = hex.charAt(b & 0x0f); - } - - return new String(hexDigest); - } - - /** - * Actually performs the download. - * Also computes the SHA1 of the file on the fly. - *

- * Success is defined as downloading as many bytes as was expected and having the same - * SHA1 as expected. Returns true on success or false if any of those checks fail. - *

- * Increments the monitor by {@link #NUM_MONITOR_INC}. - * - * @param archive The archive we're trying to download. - * @param resumeHeaders The headers to use for a partial resume, or null when fetching - * a whole new file. - * @param tmpFile The destination file to download (e.g. something.zip) - * @param propsFile A properties file generated by the last partial download (e.g. .zip.inf) - * @param urlString The URL as a string - * @param pkgName The archive's package name, used for progress output. - * @param cache The {@link DownloadCache} instance to use. - * @param monitor The monitor to output the progress and errors. - * @return True if we fetched the file successfully. - * False if the download failed or was aborted. - */ - private boolean fetchUrl(Archive archive, - Header[] resumeHeaders, - File tmpFile, - File propsFile, - String urlString, - String pkgName, - DownloadCache cache, - ITaskMonitor monitor) { - - FileOutputStream os = null; - InputStream is = null; - int inc_remain = NUM_MONITOR_INC; - try { - Pair result = - cache.openDirectUrl(urlString, resumeHeaders, monitor); - - is = result.getFirst(); - HttpResponse resp = result.getSecond(); - int status = resp.getStatusLine().getStatusCode(); - if (status == HttpStatus.SC_NOT_FOUND) { - throw new Exception("URL not found."); - } - if (is == null) { - throw new Exception("No content."); - } - - - Properties props = new Properties(); - props.setProperty(PROP_STATUS_CODE, Integer.toString(status)); - if (resp.containsHeader(HttpHeaders.ETAG)) { - props.setProperty(HttpHeaders.ETAG, - resp.getFirstHeader(HttpHeaders.ETAG).getValue()); - } - if (resp.containsHeader(HttpHeaders.LAST_MODIFIED)) { - props.setProperty(HttpHeaders.LAST_MODIFIED, - resp.getFirstHeader(HttpHeaders.LAST_MODIFIED).getValue()); - } - - try { - mFileOp.saveProperties(propsFile, props, "## Android SDK Download."); //$NON-NLS-1$ - } catch (IOException ignore) {} - - // On success, status can be: - // - 206 (Partial content), if resumeHeaders is not null (we asked for a partial - // download, and we get partial content for that download => we'll need to append - // to the existing file.) - // - 200 (OK) meaning we're getting whole new content from scratch. This can happen - // even if resumeHeaders is not null (typically means the server has a new version - // of the file to serve.) In this case we reset the file and write from scratch. - - boolean append = status == HttpStatus.SC_PARTIAL_CONTENT; - if (status != HttpStatus.SC_OK && !(append && resumeHeaders != null)) { - throw new Exception(String.format("Unexpected HTTP Status %1$d", status)); - } - MessageDigest digester = archive.getChecksumType().getMessageDigest(); - - if (append) { - // Seed the digest with the existing content. - InputStream temp = null; - try { - temp = new FileInputStream(tmpFile); - - byte[] buf = new byte[65536]; - int n; - - while ((n = temp.read(buf)) >= 0) { - if (n > 0) { - digester.update(buf, 0, n); - } - } - } catch (Exception ignore) { - } finally { - if (temp != null) { - try { - temp.close(); - } catch (IOException ignore) {} - } - } - } - - // Open the output stream in append for a resume, or reset for a full download. - os = new FileOutputStream(tmpFile, append); - - byte[] buf = new byte[65536]; - int n; - - long total = 0; - long size = archive.getSize(); - if (append) { - long len = mFileOp.length(tmpFile); - int percent = (int) (len * 100 / size); - size -= len; - monitor.logVerbose( - "Resuming %1$s download at %2$d (%3$d%%)", pkgName, len, percent); - } - long inc = size / NUM_MONITOR_INC; - long next_inc = inc; - - long startMs = System.currentTimeMillis(); - long nextMs = startMs + 2000; // start update after 2 seconds - - while ((n = is.read(buf)) >= 0) { - if (n > 0) { - os.write(buf, 0, n); - digester.update(buf, 0, n); - } - - long timeMs = System.currentTimeMillis(); - - total += n; - if (total >= next_inc) { - monitor.incProgress(1); - inc_remain--; - next_inc += inc; - } - - if (timeMs > nextMs) { - long delta = timeMs - startMs; - if (total > 0 && delta > 0) { - // percent left to download - int percent = (int) (100 * total / size); - // speed in KiB/s - float speed = (float)total / (float)delta * (1000.f / 1024.f); - // time left to download the rest at the current KiB/s rate - int timeLeft = (speed > 1e-3) ? - (int)(((size - total) / 1024.0f) / speed) : - 0; - String timeUnit = "seconds"; - if (timeLeft > 120) { - timeUnit = "minutes"; - timeLeft /= 60; - } - - monitor.setDescription( - "Downloading %1$s (%2$d%%, %3$.0f KiB/s, %4$d %5$s left)", - pkgName, - percent, - speed, - timeLeft, - timeUnit); - } - nextMs = timeMs + 1000; // update every second - } - - if (monitor.isCancelRequested()) { - monitor.log("Download aborted by user at %1$d bytes.", total); - return false; - } - - } - - if (total != size) { - monitor.logError( - "Download finished with wrong size. Expected %1$d bytes, got %2$d bytes.", - size, total); - return false; - } - - // Create an hex string from the digest - String actual = getDigestChecksum(digester); - String expected = archive.getChecksum(); - if (!actual.equalsIgnoreCase(expected)) { - monitor.logError("Download finished with wrong checksum. Expected %1$s, got %2$s.", - expected, actual); - return false; - } - - return true; - - } catch (CanceledByUserException e) { - // HTTP Basic Auth or NTLM login was canceled by user. - // Don't output an error in the log. - - } catch (FileNotFoundException e) { - // The FNF message is just the URL. Make it a bit more useful. - monitor.logError("URL not found: %1$s", e.getMessage()); - - } catch (Exception e) { - monitor.logError("Download interrupted: %1$s", e.getMessage()); //$NON-NLS-1$ - - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - // pass - } - } - - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // pass - } - } - if (inc_remain > 0) { - monitor.incProgress(inc_remain); - } - } - - return false; - } - - /** - * Install the given archive in the given folder. - */ - private boolean unarchive(ArchiveReplacement archiveInfo, - String osSdkRoot, - File archiveFile, - SdkManager sdkManager, - ITaskMonitor monitor) { - boolean success = false; - Archive newArchive = archiveInfo.getNewArchive(); - Package pkg = newArchive.getParentPackage(); - String pkgName = pkg.getShortDescription(); - monitor.setDescription("Installing %1$s", pkgName); - monitor.log("Installing %1$s", pkgName); - - // Ideally we want to always unzip in a temp folder which name depends on the package - // type (e.g. addon, tools, etc.) and then move the folder to the destination folder. - // If the destination folder exists, it will be renamed and deleted at the very - // end if everything succeeded. This provides a nice atomic swap and should leave the - // original folder untouched in case something wrong (e.g. program crash) in the - // middle of the unzip operation. - // - // However that doesn't work on Windows, we always end up not being able to move the - // new folder. There are actually 2 cases: - // A- A process such as a the explorer is locking the *old* folder or a file inside - // (e.g. adb.exe) - // In this case we really shouldn't be tried to work around it and we need to let - // the user know and let it close apps that access that folder. - // B- A process is locking the *new* folder. Very often this turns to be a file indexer - // or an anti-virus that is busy scanning the new folder that we just unzipped. - // - // So we're going to change the strategy: - // 1- Try to move the old folder to a temp/old folder. This might fail in case of issue A. - // Note: for platform-tools, we can try killing adb first. - // If it still fails, we do nothing and ask the user to terminate apps that can be - // locking that folder. - // 2- Once the old folder is out of the way, we unzip the archive directly into the - // optimal new location. We no longer unzip it in a temp folder and move it since we - // know that's what fails in most of the cases. - // 3- If the unzip fails, remove everything and try to restore the old folder by doing - // a *copy* in place and not a folder move (which will likely fail too). - - String pkgKind = pkg.getClass().getSimpleName(); - - File destFolder = null; - File oldDestFolder = null; - - try { - // -0- Compute destination directory and check install pre-conditions - - destFolder = pkg.getInstallFolder(osSdkRoot, sdkManager); - - if (destFolder == null) { - // this should not seriously happen. - monitor.log("Failed to compute installation directory for %1$s.", pkgName); - return false; - } - - if (!pkg.preInstallHook(newArchive, monitor, osSdkRoot, destFolder)) { - monitor.log("Skipping archive: %1$s", pkgName); - return false; - } - - // -1- move old folder. - - if (mFileOp.exists(destFolder)) { - // Create a new temp/old dir - if (oldDestFolder == null) { - oldDestFolder = getNewTempFolder(osSdkRoot, pkgKind, "old"); //$NON-NLS-1$ - } - if (oldDestFolder == null) { - // this should not seriously happen. - monitor.logError("Failed to find a temp directory in %1$s.", osSdkRoot); - return false; - } - - // Try to move the current dest dir to the temp/old one. Tell the user if it failed. - while(true) { - if (!moveFolder(destFolder, oldDestFolder)) { - monitor.logError("Failed to rename directory %1$s to %2$s.", - destFolder.getPath(), oldDestFolder.getPath()); - - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) { - boolean tryAgain = true; - - tryAgain = windowsDestDirLocked(osSdkRoot, destFolder, monitor); - - if (tryAgain) { - // loop, trying to rename the temp dir into the destination - continue; - } else { - return false; - } - } - } - break; - } - } - - assert !mFileOp.exists(destFolder); - - // -2- Unzip new content directly in place. - - if (!mFileOp.mkdirs(destFolder)) { - monitor.logError("Failed to create directory %1$s", destFolder.getPath()); - return false; - } - - if (!unzipFolder(archiveInfo, - archiveFile, - destFolder, - monitor)) { - return false; - } - - if (!generateSourceProperties(newArchive, destFolder)) { - monitor.logError("Failed to generate source.properties in directory %1$s", - destFolder.getPath()); - return false; - } - - // In case of success, if we were replacing an archive - // and the older one had a different path, remove it now. - Archive oldArchive = archiveInfo.getReplaced(); - if (oldArchive != null && oldArchive.isLocal()) { - String oldPath = oldArchive.getLocalOsPath(); - File oldFolder = oldPath == null ? null : new File(oldPath); - if (oldFolder == null && oldArchive.getParentPackage() != null) { - oldFolder = oldArchive.getParentPackage().getInstallFolder( - osSdkRoot, sdkManager); - } - if (oldFolder != null && mFileOp.exists(oldFolder) && - !oldFolder.equals(destFolder)) { - monitor.logVerbose("Removing old archive at %1$s", oldFolder.getAbsolutePath()); - mFileOp.deleteFileOrFolder(oldFolder); - } - } - - success = true; - pkg.postInstallHook(newArchive, monitor, destFolder); - return true; - - } finally { - if (!success) { - // In case of failure, we try to restore the old folder content. - if (oldDestFolder != null) { - restoreFolder(oldDestFolder, destFolder); - } - - // We also call the postInstallHool with a null directory to give a chance - // to the archive to cleanup after preInstallHook. - pkg.postInstallHook(newArchive, monitor, null /*installDir*/); - } - - // Cleanup if the unzip folder is still set. - mFileOp.deleteFileOrFolder(oldDestFolder); - } - } - - private boolean windowsDestDirLocked( - String osSdkRoot, - File destFolder, - final ITaskMonitor monitor) { - String msg = null; - - assert SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS; - - File findLockExe = LegacyFileOp.append( - osSdkRoot, SdkConstants.FD_TOOLS, SdkConstants.FD_LIB, SdkConstants.FN_FIND_LOCK); - - if (mFileOp.exists(findLockExe)) { - try { - final StringBuilder result = new StringBuilder(); - String command[] = new String[] { - findLockExe.getAbsolutePath(), - destFolder.getAbsolutePath() - }; - Process process = Runtime.getRuntime().exec(command); - int retCode = GrabProcessOutput.grabProcessOutput( - process, - Wait.WAIT_FOR_READERS, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - if (line != null) { - result.append(line).append("\n"); - } - } - - @Override - public void err(@Nullable String line) { - if (line != null) { - monitor.logError("[find_lock] Error: %1$s", line); - } - } - }); - - if (retCode == 0 && result.length() > 0) { - // TODO create a better dialog - - String found = result.toString().trim(); - monitor.logError("[find_lock] Directory locked by %1$s", found); - - TreeSet apps = new TreeSet(Arrays.asList( - found.split(Pattern.quote(";")))); //$NON-NLS-1$ - StringBuilder appStr = new StringBuilder(); - for (String app : apps) { - appStr.append("\n - ").append(app.trim()); //$NON-NLS-1$ - } - - msg = String.format( - "-= Warning ! =-\n" + - "The following processes: %1$s\n" + - "are locking the following directory: \n" + - " %2$s\n" + - "Please close these applications so that the installation can continue.\n" + - "When ready, press YES to try again.", - appStr.toString(), - destFolder.getPath()); - } - - } catch (Exception e) { - monitor.error(e, "[find_lock failed]"); - } - - - } - - if (msg == null) { - // Old way: simply display a generic text and let user figure it out. - msg = String.format( - "-= Warning ! =-\n" + - "A folder failed to be moved. On Windows this " + - "typically means that a program is using that folder (for " + - "example Windows Explorer or your anti-virus software.)\n" + - "Please momentarily deactivate your anti-virus software or " + - "close any running programs that may be accessing the " + - "directory '%1$s'.\n" + - "When ready, press YES to try again.", - destFolder.getPath()); - } - - boolean tryAgain = monitor.displayPrompt("SDK Manager: failed to install", msg); - return tryAgain; - } - - /** - * Tries to rename/move a folder. - *

- * Contract: - *

    - *
  • When we start, oldDir must exist and be a directory. newDir must not exist.
  • - *
  • On successful completion, oldDir must not exists. - * newDir must exist and have the same content.
  • - *
  • On failure completion, oldDir must have the same content as before. - * newDir must not exist.
  • - *
- *

- * The simple "rename" operation on a folder can typically fail on Windows for a variety - * of reason, in fact as soon as a single process holds a reference on a directory. The - * most common case are the Explorer, the system's file indexer, Tortoise SVN cache or - * an anti-virus that are busy indexing a new directory having been created. - * - * @param oldDir The old location to move. It must exist and be a directory. - * @param newDir The new location where to move. It must not exist. - * @return True if the move succeeded. On failure, we try hard to not have touched the old - * directory in order not to loose its content. - */ - private boolean moveFolder(File oldDir, File newDir) { - // This is a simple folder rename that works on Linux/Mac all the time. - // - // On Windows this might fail if an indexer is busy looking at a new directory - // (e.g. right after we unzip our archive), so it fails let's be nice and give - // it a bit of time to succeed. - for (int i = 0; i < 5; i++) { - if (mFileOp.renameTo(oldDir, newDir)) { - return true; - } - try { - Thread.sleep(500 /*ms*/); - } catch (InterruptedException e) { - // ignore - } - } - - return false; - } - - /** - * Unzips a zip file into the given destination directory. - * - * The archive file MUST have a unique "root" folder. - * This root folder is skipped when unarchiving. - */ - @SuppressWarnings("unchecked") - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected boolean unzipFolder( - ArchiveReplacement archiveInfo, - File archiveFile, - File unzipDestFolder, - ITaskMonitor monitor) { - - Archive newArchive = archiveInfo.getNewArchive(); - Package pkg = newArchive.getParentPackage(); - String pkgName = pkg.getShortDescription(); - long compressedSize = newArchive.getSize(); - - ZipFile zipFile = null; - try { - zipFile = new ZipFile(archiveFile); - - // To advance the percent and the progress bar, we don't know the number of - // items left to unzip. However we know the size of the archive and the size of - // each uncompressed item. The zip file format overhead is negligible so that's - // a good approximation. - long incStep = compressedSize / NUM_MONITOR_INC; - long incTotal = 0; - long incCurr = 0; - int lastPercent = 0; - - byte[] buf = new byte[65536]; - - Enumeration entries = zipFile.getEntries(); - while (entries.hasMoreElements()) { - ZipArchiveEntry entry = entries.nextElement(); - - String name = entry.getName(); - - // ZipFile entries should have forward slashes, but not all Zip - // implementations can be expected to do that. - name = name.replace('\\', '/'); - - // Zip entries are always packages in a top-level directory (e.g. docs/index.html). - int pos = name.indexOf('/'); - if (pos == -1) { - // All zip entries should have a root folder. - // This zip entry seems located at the root of the zip. - // Rather than ignore the file, just place it at the root. - } else if (pos == name.length() - 1) { - // This is a zip *directory* entry in the form dir/, so essentially - // it's the root directory of the SDK. It's safe to ignore that one - // since we want to use our own root directory and we'll recreate - // root directories as needed. - // A direct consequence is that if a malformed archive has multiple - // root directories, their content will all be merged together. - continue; - } else { - // This is the expected behavior: the zip entry is in the form root/file - // or root/dir/. We want to use our top-level directory so we drop the - // first segment of the path name. - name = name.substring(pos + 1); - } - - File destFile = new File(unzipDestFolder, name); - - if (name.endsWith("/")) { //$NON-NLS-1$ - // Create directory if it doesn't exist yet. This allows us to create - // empty directories. - if (!mFileOp.isDirectory(destFile) && !mFileOp.mkdirs(destFile)) { - monitor.logError("Failed to create directory %1$s", - destFile.getPath()); - return false; - } - continue; - } else if (name.indexOf('/') != -1) { - // Otherwise it's a file in a sub-directory. - - // Sanity check: since we're always unzipping in a fresh temp folder - // the destination file shouldn't already exist. - if (mFileOp.exists(destFile)) { - monitor.logVerbose("Duplicate file found: %1$s", name); - } - - // Make sure the parent directory has been created. - File parentDir = destFile.getParentFile(); - if (!mFileOp.isDirectory(parentDir)) { - if (!mFileOp.mkdirs(parentDir)) { - monitor.logError("Failed to create directory %1$s", - parentDir.getPath()); - return false; - } - } - } - - FileOutputStream fos = null; - long remains = entry.getSize(); - try { - fos = new FileOutputStream(destFile); - - // Java bug 4040920: do not rely on the input stream EOF and don't - // try to read more than the entry's size. - InputStream entryContent = zipFile.getInputStream(entry); - int n; - while (remains > 0 && - (n = entryContent.read( - buf, 0, (int) Math.min(remains, buf.length))) != -1) { - remains -= n; - if (n > 0) { - fos.write(buf, 0, n); - } - } - } catch (EOFException e) { - monitor.logError("Error uncompressing file %s. Size: %d bytes, Unwritten: %d bytes.", - entry.getName(), entry.getSize(), remains); - throw e; - } finally { - if (fos != null) { - fos.close(); - } - } - - pkg.postUnzipFileHook(newArchive, monitor, mFileOp, destFile, entry); - - // Increment progress bar to match. We update only between files. - for(incTotal += entry.getCompressedSize(); incCurr < incTotal; incCurr += incStep) { - monitor.incProgress(1); - } - - int percent = (int) (100 * incTotal / compressedSize); - if (percent != lastPercent) { - monitor.setDescription("Unzipping %1$s (%2$d%%)", pkgName, percent); - lastPercent = percent; - } - - if (monitor.isCancelRequested()) { - return false; - } - } - - return true; - - } catch (IOException e) { - monitor.logError("Unzip failed: %1$s", e.getMessage()); - - } finally { - if (zipFile != null) { - try { - zipFile.close(); - } catch (IOException e) { - // pass - } - } - } - - return false; - } - - /** - * Returns an unused temp folder path in the form of osBasePath/temp/prefix.suffixNNN. - *

- * This does not actually create the folder. It just scan the base path for - * a free folder name to use and returns the file to use to reference it. - *

- * This operation is not atomic so there's no guarantee the folder can't get - * created in between. This is however unlikely and the caller can assume the - * returned folder does not exist yet. - *

- * Returns null if no such folder can be found (e.g. if all candidates exist, - * which is rather unlikely) or if the base temp folder cannot be created. - */ - private File getNewTempFolder(String osBasePath, String prefix, String suffix) { - File baseTempFolder = getTempFolder(osBasePath); - - if (!mFileOp.isDirectory(baseTempFolder)) { - if (mFileOp.isFile(baseTempFolder)) { - mFileOp.deleteFileOrFolder(baseTempFolder); - } - if (!mFileOp.mkdirs(baseTempFolder)) { - return null; - } - } - - for (int i = 1; i < 100; i++) { - File folder = new File(baseTempFolder, - String.format("%1$s.%2$s%3$02d", prefix, suffix, i)); //$NON-NLS-1$ - if (!mFileOp.exists(folder)) { - return folder; - } - } - return null; - } - - /** - * Returns the single fixed "temp" folder used by the SDK Manager. - * This folder is always at osBasePath/temp. - *

- * This does not actually create the folder. - */ - private File getTempFolder(String osBasePath) { - File baseTempFolder = new File(osBasePath, RepoConstants.FD_TEMP); - return baseTempFolder; - } - - /** - * Generates a source.properties in the destination folder that contains all the infos - * relevant to this archive, this package and the source so that we can reload them - * locally later. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected boolean generateSourceProperties(Archive archive, File unzipDestFolder) { - - // Create a version of Properties that returns a sorted key set. - // This is used by Properties#saveProperties and should ensure the - // properties are in a stable order. Unit tests rely on this fact. - @SuppressWarnings("serial") - Properties props = new Properties() { - @Override - public synchronized Enumeration keys() { - Set sortedSet = new TreeSet(keySet()); - final Iterator it = sortedSet.iterator(); - return new Enumeration() { - @Override - public boolean hasMoreElements() { - return it.hasNext(); - } - - @Override - public Object nextElement() { - return it.next(); - } - - }; - } - }; - - archive.saveProperties(props); - - Package pkg = archive.getParentPackage(); - if (pkg != null) { - pkg.saveProperties(props); - } - - try { - mFileOp.saveProperties( - new File(unzipDestFolder, SdkConstants.FN_SOURCE_PROP), - props, - "## Android Tool: Source of this archive."); //$NON-NLS-1$ - return true; - } catch (IOException ignore) { - return false; - } - } - - /** - * Recursively restore srcFolder into destFolder by performing a copy of the file - * content rather than rename/moves. - * - * @param srcFolder The source folder to restore. - * @param destFolder The destination folder where to restore. - * @return True if the folder was successfully restored, false if it was not at all or - * only partially restored. - */ - private boolean restoreFolder(File srcFolder, File destFolder) { - boolean result = true; - - // Process sub-folders first - File[] srcFiles = mFileOp.listFiles(srcFolder); - if (srcFiles == null) { - // Source does not exist. That is quite odd. - return false; - } - - if (mFileOp.isFile(destFolder)) { - if (!mFileOp.delete(destFolder)) { - // There's already a file in there where we want a directory and - // we can't delete it. This is rather unexpected. Just give up on - // that folder. - return false; - } - } else if (!mFileOp.isDirectory(destFolder)) { - mFileOp.mkdirs(destFolder); - } - - // Get all the files and dirs of the current destination. - // We are not going to clean up the destination first. - // Instead we'll copy over and just remove any remaining files or directories. - Set destDirs = new HashSet(); - Set destFiles = new HashSet(); - File[] files = mFileOp.listFiles(destFolder); - if (files != null) { - for (File f : files) { - if (mFileOp.isDirectory(f)) { - destDirs.add(f); - } else { - destFiles.add(f); - } - } - } - - // First restore all source directories. - for (File dir : srcFiles) { - if (mFileOp.isDirectory(dir)) { - File d = new File(destFolder, dir.getName()); - destDirs.remove(d); - if (!restoreFolder(dir, d)) { - result = false; - } - } - } - - // Remove any remaining directories not processed above. - for (File dir : destDirs) { - mFileOp.deleteFileOrFolder(dir); - } - - // Copy any source files over to the destination. - for (File file : srcFiles) { - if (mFileOp.isFile(file)) { - File f = new File(destFolder, file.getName()); - destFiles.remove(f); - try { - mFileOp.copyFile(file, f); - } catch (IOException e) { - result = false; - } - } - } - - // Remove any remaining files not processed above. - for (File file : destFiles) { - mFileOp.deleteFileOrFolder(file); - } - - return result; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveReplacement.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveReplacement.java deleted file mode 100644 index 4cf85f2c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ArchiveReplacement.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.archives; - -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.packages.Package; - - -/** - * Represents an archive that we want to install and the archive that it is - * going to replace, if any. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ArchiveReplacement implements IDescription { - - private final Archive mNewArchive; - private final Archive mReplaced; - - /** - * Creates a new replacement where the {@code newArchive} will replace the - * currently installed {@code replaced} archive. - * When {@code newArchive} is not intended to replace anything (e.g. because - * the user is installing a new package not present on her system yet), then - * {@code replace} shall be null. - * - * @param newArchive A "new archive" to be installed. This is always an archive - * that comes from a remote site. This may be null. - * @param replaced An optional local archive that the new one will replace. - * Can be null if this archive does not replace anything. - */ - public ArchiveReplacement(Archive newArchive, Archive replaced) { - mNewArchive = newArchive; - mReplaced = replaced; - } - - /** - * Returns the "new archive" to be installed. - * This may be null for missing archives. - */ - public Archive getNewArchive() { - return mNewArchive; - } - - /** - * Returns an optional local archive that the new one will replace. - * Can be null if this archive does not replace anything. - */ - public Archive getReplaced() { - return mReplaced; - } - - /** - * Returns the long description of the parent package of the new archive, if not null. - * Otherwise returns an empty string. - */ - @Override - public String getLongDescription() { - if (mNewArchive != null) { - Package p = mNewArchive.getParentPackage(); - if (p != null) { - return p.getLongDescription(); - } - } - return ""; - } - - /** - * Returns the short description of the parent package of the new archive, if not null. - * Otherwise returns an empty string. - */ - @Override - public String getShortDescription() { - if (mNewArchive != null) { - Package p = mNewArchive.getParentPackage(); - if (p != null) { - return p.getShortDescription(); - } - } - return ""; - } - - /** - * Returns the short description of the parent package of the new archive, if not null. - * Otherwise returns the default Object toString result. - *

- * This is mostly helpful for debugging. For UI display, use the {@link IDescription} - * interface. - */ - @Override - public String toString() { - if (mNewArchive != null) { - Package p = mNewArchive.getParentPackage(); - if (p != null) { - return p.getShortDescription(); - } - } - return super.toString(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/BitSize.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/BitSize.java deleted file mode 100644 index 5f72c76f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/BitSize.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2014 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.internal.repository.archives; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; - -/** - * The Architecture that this archive can be downloaded on. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum BitSize { - _32(32), - _64(64); - - private final int mSize; - - BitSize(int size) { - mSize = size; - } - - /** Returns the size of the architecture. */ - public int getSize() { - return mSize; - } - - /** Returns the XML name of the bit size. */ - @NonNull - public String getXmlName() { - return Integer.toString(mSize); - } - /** - * Returns the enum value matching the given XML name. - * @return A valid {@link HostOs} constant or null if not a valid XML name. - */ - @Nullable - public static BitSize fromXmlName(@Nullable String xmlName) { - if (xmlName != null) { - for (BitSize v : values()) { - if (v.getXmlName().equalsIgnoreCase(xmlName)) { - return v; - } - } - } - return null; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ChecksumType.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ChecksumType.java deleted file mode 100644 index 93049345..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/ChecksumType.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.archives; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * The checksum type. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum ChecksumType { - /** A SHA1 checksum, represented as a 40-hex string. */ - SHA1("SHA-1"); //$NON-NLS-1$ - - private final String mAlgorithmName; - - /** - * Constructs a {@link ChecksumType} with the algorithm name - * suitable for {@link MessageDigest#getInstance(String)}. - *

- * These names are officially documented at - * http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html#MessageDigest - */ - ChecksumType(String algorithmName) { - mAlgorithmName = algorithmName; - } - - /** - * Returns a new {@link MessageDigest} instance for this checksum type. - * @throws NoSuchAlgorithmException if this algorithm is not available. - */ - public MessageDigest getMessageDigest() throws NoSuchAlgorithmException { - return MessageDigest.getInstance(mAlgorithmName); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/HostOs.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/HostOs.java deleted file mode 100644 index 6c7d4431..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/HostOs.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2014 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.internal.repository.archives; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; - -import java.util.Locale; - -/** - * The OS that this archive can be downloaded on.
- * The represents a "host" where the SDK tools and the SDK Manager can run, - * not the Android device targets. - *

- * The actual OS requirements for the SDK are listed at - * http://d.android.com/sdk - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum HostOs { - /** Any of the Unix-like host OSes. */ - LINUX("Linux"), - /** Any variation of MacOS X. */ - MACOSX("MacOS X"), - /** Any variation of Windows. */ - WINDOWS("Windows"); - - private final String mUiName; - - HostOs(@NonNull String uiName) { - mUiName = uiName; - } - - /** - * Returns the UI name of the OS. - */ - @NonNull - public String getUiName() { - return mUiName; - } - - /** - * Returns the XML name of the OS. - * @returns Null, windows, macosx or linux. - */ - @NonNull - public String getXmlName() { - return toString().toLowerCase(Locale.US); - } - - /** - * Returns the enum value matching the given XML name. - * @return A valid {@link HostOs} constnat or null if not a valid XML name. - */ - @Nullable - public static HostOs fromXmlName(@Nullable String xmlName) { - if (xmlName != null) { - for (HostOs v : values()) { - if (v.getXmlName().equalsIgnoreCase(xmlName)) { - return v; - } - } - } - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyArch.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyArch.java deleted file mode 100644 index 51d78dc7..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyArch.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2014 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.internal.repository.archives; - - - -/** - * The legacy Architecture that this archive can be downloaded on. - *

- * This attribute was used for the <archive> element in repo schema 1-9. - * add-on schema 1-6 and sys-img schema 1-2. - * Starting with repo schema 10, add-on schema 7 and sys-img schema 3, this is replaced - * by the <host-bit> and <jvm-bit> elements and {@link ArchFilter}. - * - * @see HostOs - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum LegacyArch { - ANY("Any"), - PPC("PowerPC"), - X86("x86"), - X86_64("x86_64"); - - private final String mUiName; - - LegacyArch(String uiName) { - mUiName = uiName; - } - - /** Returns the UI name of the architecture. */ - public String getUiName() { - return mUiName; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyOs.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyOs.java deleted file mode 100644 index 2f096b47..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/archives/LegacyOs.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2014 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.internal.repository.archives; - - - -/** - * The legacy OS that this archive can be downloaded on. - *

- * This attribute was used for the <archive> element in repo schema 1-9. - * add-on schema 1-6 and sys-img schema 1-2. - * Starting with repo schema 10, add-on schema 7 and sys-img schema 3, this is replaced - * by the <host-os> element and {@link ArchFilter}. - * - * @see HostOs - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum LegacyOs { - ANY("Any"), - LINUX("Linux"), - MACOSX("MacOS X"), - WINDOWS("Windows"); - - private final String mUiName; - - LegacyOs(String uiName) { - mUiName = uiName; - } - - /** Returns the UI name of the OS. */ - public String getUiName() { - return mUiName; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/AddonPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/AddonPackage.java deleted file mode 100644 index f5c404db..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/AddonPackage.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.IAndroidTarget.OptionalLibrary; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.AddonManifestIniProps; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.sdklib.repository.local.LocalAddonPkgInfo; -import com.android.utils.Pair; -import com.google.common.collect.ImmutableList; - -import org.w3c.dom.Node; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; - -/** - * Represents an add-on XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class AddonPackage extends MajorRevisionPackage - implements IAndroidVersionProvider, IPlatformDependency, - IExactApiLevelDependency, ILayoutlibVersion { - - private final String mVendorId; - private final String mVendorDisplay; - private final String mNameId; - private final String mDisplayName; - private final AndroidVersion mVersion; - private final IPkgDesc mPkgDesc; - - /** - * The helper handling the layoutlib version. - */ - private final LayoutlibVersionMixin mLayoutlibVersion; - - /** An add-on library. */ - public static class Lib { - private final String mName; - private final String mDescription; - - public Lib(String name, String description) { - mName = name; - mDescription = description; - } - - public String getName() { - return mName; - } - - public String getDescription() { - return mDescription; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mDescription == null) ? 0 : mDescription.hashCode()); - result = prime * result + ((mName == null) ? 0 : mName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof Lib)) { - return false; - } - Lib other = (Lib) obj; - if (mDescription == null) { - if (other.mDescription != null) { - return false; - } - } else if (!mDescription.equals(other.mDescription)) { - return false; - } - if (mName == null) { - if (other.mName != null) { - return false; - } - } else if (!mName.equals(other.mName)) { - return false; - } - return true; - } - } - - private final Lib[] mLibs; - - /** - * Creates a new add-on package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public AddonPackage( - SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - // --- name id/display --- - // addon-4.xsd introduces the name-id, name-display, vendor-id and vendor-display. - // These are not optional but we still need to support a fallback for older addons - // that only provide name and vendor. If the addon provides neither set of fields, - // it will simply not work as expected. - - String nameId = PackageParserUtils.getXmlString(packageNode, - SdkRepoConstants.NODE_NAME_ID); - String nameDisp = PackageParserUtils.getXmlString(packageNode, - SdkRepoConstants.NODE_NAME_DISPLAY); - String name = PackageParserUtils.getXmlString(packageNode, - SdkRepoConstants.NODE_NAME); - - // The old is equivalent to the new - if (nameDisp.isEmpty()) { - nameDisp = name; - } - - // For a missing id, we simply use a sanitized version of the display name - if (nameId.isEmpty()) { - nameId = LocalAddonPkgInfo.sanitizeDisplayToNameId(!name.isEmpty() ? name : nameDisp); - } - - assert !nameId.isEmpty(); - assert !nameDisp.isEmpty(); - - mNameId = nameId.trim(); - mDisplayName = nameDisp.trim(); - - // --- vendor id/display --- - // Same processing for vendor id vs display - - String vendorId = PackageParserUtils.getXmlString(packageNode, - SdkAddonConstants.NODE_VENDOR_ID); - String vendorDisp = PackageParserUtils.getXmlString(packageNode, - SdkAddonConstants.NODE_VENDOR_DISPLAY); - String vendor = PackageParserUtils.getXmlString(packageNode, - SdkAddonConstants.NODE_VENDOR); - - // The old is equivalent to the new - if (vendorDisp.isEmpty()) { - vendorDisp = vendor; - } - - // For a missing id, we simply use a sanitized version of the display vendor - if (vendorId.isEmpty()) { - boolean hasVendor = !vendor.isEmpty(); - vendorId = LocalAddonPkgInfo.sanitizeDisplayToNameId(hasVendor ? vendor : vendorDisp); - } - - assert !vendorId.isEmpty(); - assert !vendorDisp.isEmpty(); - - mVendorId = vendorId.trim(); - mVendorDisplay = vendorDisp.trim(); - - // --- other attributes - - int apiLevel = - PackageParserUtils.getXmlInt(packageNode, SdkAddonConstants.NODE_API_LEVEL, 0); - mVersion = new AndroidVersion(apiLevel, null /*codeName*/); - - mLibs = parseLibs( - PackageParserUtils.findChildElement(packageNode, SdkAddonConstants.NODE_LIBS)); - - mLayoutlibVersion = new LayoutlibVersionMixin(packageNode); - - mPkgDesc = setDescriptions( - PkgDesc.Builder.newAddon(mVersion, (MajorRevision) getRevision(), - new IdDisplay(mVendorId, mVendorDisplay), - new IdDisplay(mNameId, mDisplayName))) - .create(); - } - - /** - * Creates a new platform package based on an actual {@link IAndroidTarget} (which - * {@link IAndroidTarget#isPlatform()} false) from the {@link SdkManager}. - * This is used to list local SDK folders in which case there is one archive which - * URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create(IAndroidTarget target, Properties props) { - return new AddonPackage(target, props); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected AddonPackage(IAndroidTarget target, Properties props) { - this(null /*source*/, target, props); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected AddonPackage(SdkSource source, IAndroidTarget target, Properties props) { - super( source, //source - props, //properties - target.getRevision(), //revision - null, //license - target.getDescription(), //description - null, //descUrl - target.getLocation() //archiveOsPath - ); - - // --- name id/display --- - // addon-4.xsd introduces the name-id, name-display, vendor-id and vendor-display. - // These are not optional but we still need to support a fallback for older addons - // that only provide name and vendor. If the addon provides neither set of fields, - // it will simply not work as expected. - - String nameId = getProperty(props, PkgProps.ADDON_NAME_ID, ""); //$NON-NLS-1$ - String nameDisp = getProperty(props, PkgProps.ADDON_NAME_DISPLAY, ""); //$NON-NLS-1$ - String name = getProperty(props, PkgProps.ADDON_NAME, target.getName()); - - // The old is equivalent to the new - //noinspection ConstantConditions - if (nameDisp.isEmpty()) { - nameDisp = name; - } - - // For a missing id, we simply use a sanitized version of the display name - //noinspection ConstantConditions - if (nameId.isEmpty()) { - nameId = LocalAddonPkgInfo.sanitizeDisplayToNameId(!name.isEmpty() ? name : nameDisp); - } - - assert !nameId.isEmpty(); - assert !nameDisp.isEmpty(); - - mNameId = nameId.trim(); - mDisplayName = nameDisp.trim(); - - // --- vendor id/display --- - // Same processing for vendor id vs display - - String vendorId = getProperty(props, PkgProps.ADDON_VENDOR_ID, ""); //$NON-NLS-1$ - String vendorDisp = getProperty(props, PkgProps.ADDON_VENDOR_DISPLAY, ""); //$NON-NLS-1$ - String vendor = getProperty(props, PkgProps.ADDON_VENDOR, target.getVendor()); - - // The old is equivalent to the new - //noinspection ConstantConditions - if (vendorDisp.isEmpty()) { - vendorDisp = vendor; - } - - // For a missing id, we simply use a sanitized version of the display vendor - //noinspection ConstantConditions - if (vendorId.isEmpty()) { - //noinspection ConstantConditions - boolean hasVendor = !vendor.isEmpty(); - vendorId = LocalAddonPkgInfo.sanitizeDisplayToNameId(hasVendor ? vendor : vendorDisp); - } - - assert !vendorId.isEmpty(); - assert !vendorDisp.isEmpty(); - - mVendorId = vendorId.trim(); - mVendorDisplay = vendorDisp.trim(); - - // --- other attributes - - mVersion = target.getVersion(); - mLayoutlibVersion = new LayoutlibVersionMixin(props); - - List optLibs = target.getAdditionalLibraries(); - if (optLibs.isEmpty()) { - mLibs = new Lib[0]; - } else { - mLibs = new Lib[optLibs.size()]; - for (int i = 0; i < optLibs.size(); i++) { - OptionalLibrary optionalLibrary = optLibs.get(i); - mLibs[i] = new Lib(optionalLibrary.getName(), optionalLibrary.getDescription()); - } - } - - mPkgDesc = setDescriptions( - PkgDesc.Builder.newAddon(mVersion, (MajorRevision) getRevision(), - new IdDisplay(mVendorId, mVendorDisplay), - new IdDisplay(mNameId, mDisplayName))) - .create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Creates a broken addon which we know failed to load properly. - * - * @param archiveOsPath The absolute OS path of the addon folder. - * @param sourceProps The properties parsed from the addon's source.properties. Can be null. - * @param addonProps The properties parsed from the addon manifest (NOT the source.properties). - * @param error The error indicating why this addon failed to be loaded. - */ - public static Package createBroken( - String archiveOsPath, - Properties sourceProps, - Map addonProps, - String error) { - - - String nameId = getProperty(sourceProps, PkgProps.ADDON_NAME_ID, null); - String nameDisp = getProperty(sourceProps, PkgProps.ADDON_NAME_DISPLAY, null); - if (nameDisp == null) { - nameDisp = getProperty(sourceProps, PkgProps.ADDON_NAME_DISPLAY, null); - } - if (nameDisp == null) { - nameDisp = addonProps.get(AddonManifestIniProps.ADDON_NAME); - } - if (nameDisp == null) { - nameDisp = "Unknown"; - } - if (nameId == null) { - nameId = LocalAddonPkgInfo.sanitizeDisplayToNameId(nameDisp); - } - - String vendorId = getProperty(sourceProps, PkgProps.ADDON_VENDOR_ID, null); - String vendorDisp = getProperty(sourceProps, PkgProps.ADDON_VENDOR_DISPLAY, null); - if (vendorDisp == null) { - vendorDisp = getProperty(sourceProps, PkgProps.ADDON_VENDOR_DISPLAY, null); - } - if (vendorDisp == null) { - vendorDisp = addonProps.get(AddonManifestIniProps.ADDON_VENDOR); - } - if (vendorDisp == null) { - vendorDisp = "Unknown"; - } - if (vendorId == null) { - vendorId = LocalAddonPkgInfo.sanitizeDisplayToNameId(vendorDisp); - } - - String api = addonProps.get(AddonManifestIniProps.ADDON_API); - String revision = addonProps.get(AddonManifestIniProps.ADDON_REVISION); - - String shortDesc = String.format("%1$s by %2$s, Android API %3$s, revision %4$s [*]", - nameDisp, - vendorDisp, - api, - revision); - - String longDesc = String.format( - "%1$s\n" + - "[*] Addon failed to load: %2$s", - shortDesc, - error); - - int apiLevel = IExactApiLevelDependency.API_LEVEL_INVALID; - - try { - apiLevel = Integer.parseInt(api); - } catch(NumberFormatException ignore) {} - - int intRevision = MajorRevision.MISSING_MAJOR_REV; - try { - intRevision = Integer.parseInt(revision); - } catch (NumberFormatException ignore) {} - - IPkgDesc desc = PkgDesc.Builder - .newAddon(new AndroidVersion(apiLevel, null), - new MajorRevision(intRevision), - new IdDisplay(vendorId, vendorDisp), - new IdDisplay(nameId, nameDisp)) - .setDescriptionShort(shortDesc) - .create(); - - return new BrokenPackage(null/*props*/, shortDesc, longDesc, - IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, - apiLevel, - archiveOsPath, - desc); - } - - @Override - public int getExactApiLevel() { - return mVersion.getApiLevel(); - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - mVersion.saveProperties(props); - mLayoutlibVersion.saveProperties(props); - - props.setProperty(PkgProps.ADDON_NAME_ID, mNameId); - props.setProperty(PkgProps.ADDON_NAME_DISPLAY, mDisplayName); - props.setProperty(PkgProps.ADDON_VENDOR_ID, mVendorId); - props.setProperty(PkgProps.ADDON_VENDOR_DISPLAY, mVendorDisplay); - } - - /** - * Parses a element. - */ - private Lib[] parseLibs(Node libsNode) { - ArrayList libs = new ArrayList(); - - if (libsNode != null) { - String nsUri = libsNode.getNamespaceURI(); - for(Node child = libsNode.getFirstChild(); - child != null; - child = child.getNextSibling()) { - - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI()) && - SdkRepoConstants.NODE_LIB.equals(child.getLocalName())) { - libs.add(parseLib(child)); - } - } - } - - return libs.toArray(new Lib[libs.size()]); - } - - /** - * Parses a element from a container. - */ - private Lib parseLib(Node libNode) { - return new Lib(PackageParserUtils.getXmlString(libNode, SdkRepoConstants.NODE_NAME), - PackageParserUtils.getXmlString(libNode, SdkRepoConstants.NODE_DESCRIPTION)); - } - - /** Returns the vendor id, a string, for add-on packages. */ - @NonNull - public String getVendorId() { - return mVendorId; - } - - /** Returns the vendor, a string for display purposes. */ - @NonNull - public String getDisplayVendor() { - return mVendorDisplay; - } - - /** Returns the name id, a string, for add-on packages or for libraries. */ - @NonNull - public String getNameId() { - return mNameId; - } - - /** Returns the name, a string for display purposes. */ - @NonNull - public String getDisplayName() { - return mDisplayName; - } - - /** - * Returns the version of the platform dependency of this package. - *

- * An add-on has the same {@link AndroidVersion} as the platform it depends on. - */ - @Override @NonNull - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** Returns the libs defined in this add-on. Can be an empty array but not null. */ - @NonNull - public Lib[] getLibs() { - return mLibs; - } - - /** - * Returns the layoutlib version. - *

- * The first integer is the API of layoublib, which should be > 0. - * It will be equal to {@link ILayoutlibVersion#LAYOUTLIB_API_NOT_SPECIFIED} (0) - * if the layoutlib version isn't specified. - *

- * The second integer is the revision for that given API. It is >= 0 - * and works as a minor revision number, incremented for the same API level. - * - * @since sdk-addon-2.xsd - */ - @NonNull - @Override - public Pair getLayoutlibVersion() { - return mLayoutlibVersion.getLayoutlibVersion(); - } - - /** - * Returns a string identifier to install this package from the command line. - * For add-ons, we use "addon-vendor-name-N" where N is the base platform API. - *

- * {@inheritDoc} - */ - @NonNull - @Override - public String installId() { - return encodeAddonName(); - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("%1$s%2$s", - getDisplayName(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("%1$s, Android API %2$s, revision %3$s%4$s", - getDisplayName(), - mVersion.getApiString(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = String.format("%1$s, Android API %2$s, revision %3$s%4$s\nBy %5$s", - getDisplayName(), - mVersion.getApiString(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : "", //$NON-NLS-2$ - getDisplayVendor()); - - String d = getDescription(); - if (d != null && !d.isEmpty()) { - s += '\n' + d; - } - - s += String.format("\nRequires SDK Platform Android API %1$s", - mVersion.getApiString()); - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * An add-on package is typically installed in SDK/add-ons/"addon-name"-"api-level". - * The name needs to be sanitized to be acceptable as a directory name. - * However if we can find a different directory under SDK/add-ons that already - * has this add-ons installed, we'll use that one. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - File addons = new File(osSdkRoot, SdkConstants.FD_ADDONS); - - // First find if this add-on is already installed. If so, reuse the same directory. - for (IAndroidTarget target : sdkManager.getTargets()) { - if (!target.isPlatform() && target.getVersion().equals(mVersion)) { - // Starting with addon-4.xsd, the addon source.properties differentiate - // between ids and display strings. However the addon target which relies - // on the manifest.ini does not so we need to cover both cases. - // TODO fix when we get rid of manifest.ini for addons - if ((target.getName().equals(getNameId()) && - target.getVendor().equals(getVendorId())) || - (target.getName().equals(getDisplayName()) && - target.getVendor().equals(getDisplayVendor()))) { - return new File(target.getLocation()); - } - } - } - - // Compute a folder directory using the addon declared name and vendor strings. - String name = encodeAddonName(); - - for (int i = 0; i < 100; i++) { - String name2 = i == 0 ? name : String.format("%s-%d", name, i); //$NON-NLS-1$ - File folder = new File(addons, name2); - if (!folder.exists()) { - return folder; - } - } - - // We shouldn't really get here. I mean, seriously, we tried hard enough. - return null; - } - - private String encodeAddonName() { - String name = String.format("addon-%s-%s-%s", //$NON-NLS-1$ - getNameId(), getVendorId(), mVersion.getApiString()); - name = name.toLowerCase(Locale.US); - name = name.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - name = name.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - return name; - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof AddonPackage) { - AddonPackage newPkg = (AddonPackage)pkg; - - // check they are the same add-on. - if (getNameId().equals(newPkg.getNameId()) && - getAndroidVersion().equals(newPkg.getAndroidVersion())) { - // Check the vendor-id field. - if (getVendorId().equals(newPkg.getVendorId())) { - return true; - } - - // When loading addons from the v3 schema that only had a - // field, the vendor field has been converted to vendor-display so - // as a transition mechanism we should test this also. - // TODO: in a couple iterations of the SDK Manager, remove this check - // and only compare using the vendor-id field. - return getDisplayVendor().equals(newPkg.getDisplayVendor()); - } - } - - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mLayoutlibVersion == null) ? 0 : mLayoutlibVersion.hashCode()); - result = prime * result + Arrays.hashCode(mLibs); - result = prime * result + ((mDisplayName == null) ? 0 : mDisplayName.hashCode()); - result = prime * result + ((mVendorDisplay == null) ? 0 : mVendorDisplay.hashCode()); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof AddonPackage)) { - return false; - } - AddonPackage other = (AddonPackage) obj; - if (mLayoutlibVersion == null) { - if (other.mLayoutlibVersion != null) { - return false; - } - } else if (!mLayoutlibVersion.equals(other.mLayoutlibVersion)) { - return false; - } - if (!Arrays.equals(mLibs, other.mLibs)) { - return false; - } - if (mNameId == null) { - if (other.mNameId != null) { - return false; - } - } else if (!mNameId.equals(other.mNameId)) { - return false; - } - if (mVendorId == null) { - if (other.mVendorId != null) { - return false; - } - } else if (!mVendorId.equals(other.mVendorId)) { - return false; - } - if (mVersion == null) { - if (other.mVersion != null) { - return false; - } - } else if (!mVersion.equals(other.mVersion)) { - return false; - } - return true; - } - - /** - * For addon packages, we want to add vendor|name to the sorting key - * before the revision number. - *

- * {@inheritDoc} - */ - @Override - protected String comparisonKey() { - String s = super.comparisonKey(); - int pos = s.indexOf("|r:"); //$NON-NLS-1$ - assert pos > 0; - s = s.substring(0, pos) + - "|vid:" + getVendorId() + //$NON-NLS-1$ - "|nid:" + getNameId() + //$NON-NLS-1$ - s.substring(pos); - return s; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BrokenPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BrokenPackage.java deleted file mode 100644 index 3ee5ed28..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BrokenPackage.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Represents an SDK repository package that is incomplete. - * It has a distinct icon and a specific error that is supposed to help the user on how to fix it. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class BrokenPackage extends MajorRevisionPackage - implements IExactApiLevelDependency, IMinApiLevelDependency { - - /** - * The minimal API level required by this package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - private final int mMinApiLevel; - - /** - * The exact API level required by this package, if > 0, - * or {@link #API_LEVEL_INVALID} if there is no such requirement. - */ - private final int mExactApiLevel; - - private final String mShortDescription; - private final String mLongDescription; - private final IPkgDesc mPkgDesc; - - /** - * Creates a new "broken" package that represents a package that we failed to load, - * for whatever error indicated in {@code longDescription}. - * There is also an optional API level dependency that can be specified. - *

- * By design, this creates a package with one and only one archive. - */ - BrokenPackage(@Nullable Properties props, - @NonNull String shortDescription, - @NonNull String longDescription, - int minApiLevel, - int exactApiLevel, - @Nullable String archiveOsPath, - @NonNull IPkgDesc pkgDesc) { - super( null, //source - props, //properties - 0, //revision will be taken from props - null, //license - longDescription, //description - null, //descUrl - archiveOsPath //archiveOsPath - ); - mShortDescription = shortDescription; - mLongDescription = longDescription; - mMinApiLevel = minApiLevel; - mExactApiLevel = exactApiLevel; - mPkgDesc = pkgDesc; - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - *

- * Base implementation override: We don't actually save properties for a broken package. - */ - @Override - public void saveProperties(Properties props) { - // Nop. We don't actually save properties for a broken package. - } - - /** - * Returns the minimal API level required by this package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public int getMinApiLevel() { - return mMinApiLevel; - } - - /** - * Returns the exact API level required by this package, if > 0, - * or {@link #API_LEVEL_INVALID} if the value was missing. - */ - @Override - public int getExactApiLevel() { - return mExactApiLevel; - } - - /** - * Returns a string identifier to install this package from the command line. - * For broken packages, we return an empty string. These are not installable. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return ""; //$NON-NLS-1$ - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - return mShortDescription; - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - return mShortDescription; - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description uses what was given to the constructor. - * If it's missing, it will use whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - - String s = mLongDescription; - if (s != null && !s.isEmpty()) { - return s; - } - - s = getDescription(); - if (s != null && !s.isEmpty()) { - return s; - } - return getShortDescription(); - } - - /** - * We should not be attempting to install a broken package. - * - * {@inheritDoc} - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - // We should not be attempting to install a broken package. - return null; - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof BrokenPackage) { - return mShortDescription.equals(((BrokenPackage) pkg).mShortDescription) && - getDescription().equals(pkg.getDescription()) && - getMinApiLevel() == ((BrokenPackage) pkg).getMinApiLevel(); - } - - return false; - } - - @Override - public boolean preInstallHook(Archive archive, - ITaskMonitor monitor, - String osSdkRoot, - File installFolder) { - // Nothing specific to do. - return super.preInstallHook(archive, monitor, osSdkRoot, installFolder); - } - - /** - * Computes a hash of the installed content (in case of successful install.) - * - * {@inheritDoc} - */ - @Override - public void postInstallHook(Archive archive, ITaskMonitor monitor, File installFolder) { - // Nothing specific to do. - super.postInstallHook(archive, monitor, installFolder); - } - - /** - * Similar to {@link BuildToolPackage#comparisonKey()}, but we need to use - * {@link #getPkgDesc} instead of {@link #getRevision()} - */ - @Override - protected String comparisonKey() { - String s = super.comparisonKey(); - FullRevision rev = getPkgDesc().getFullRevision(); - if (rev != null) { - int pos = s.indexOf("|r:"); //$NON-NLS-1$ - assert pos > 0; - String reverseSort = String.format("|rr:%1$04d.%2$04d.%3$04d.", //$NON-NLS-1$ - 9999 - rev.getMajor(), - 9999 - rev.getMinor(), - 9999 - rev.getMicro()); - - s = s.substring(0, pos) + reverseSort + s.substring(pos); - } - return s; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BuildToolPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BuildToolPackage.java deleted file mode 100644 index 2aa30aeb..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/BuildToolPackage.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (C) 2013 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.PreciseRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import org.w3c.dom.Node; - -import java.io.File; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - * Represents a build-tool XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class BuildToolPackage extends FullRevisionPackage { - - /** The base value returned by {@link BuildToolPackage#installId()}. */ - private static final String INSTALL_ID_BASE = SdkConstants.FD_BUILD_TOOLS + '-'; - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new build-tool package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public BuildToolPackage( - SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newBuildTool(getRevision()) - ) - .create(); - } - - /** - * Creates either a valid {@link BuildToolPackage} or a {@link BrokenPackage}. - *

- * If the build-tool directory contains valid properties, - * this creates a new {@link BuildToolPackage} with the reversion listed in the properties. - * Otherwise returns a new {@link BrokenPackage} with some explanation on what failed. - *

- * Note that the folder name is not enforced. A build-tool directory must have a - * a source.props with a revision property and a few expected binaries inside to be - * valid. - * - * @param buildToolDir The SDK/build-tool/revision folder - * @param props The properties located in {@code buildToolDir} or null if not found. - * @return A new {@link BuildToolPackage} or a new {@link BrokenPackage}. - */ - public static Package create(File buildToolDir, Properties props) { - String error = null; - - // Try to load the reversion from the sources.props. - // If we don't find them, the package is broken. - if (props == null) { - error = String.format("Missing file %1$s in build-tool/%2$s", - SdkConstants.FN_SOURCE_PROP, - buildToolDir.getName()); - } - - // Check we can find the revision in the source properties - FullRevision rev = null; - if (error == null) { - String revStr = getProperty(props, PkgProps.PKG_REVISION, null); - - if (revStr != null) { - try { - rev = FullRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - if (rev == null) { - error = String.format("Missing revision property in %1$s", - SdkConstants.FN_SOURCE_PROP); - } - } - - if (error == null) { - // Check the directory contains the expected binaries. - - if (!buildToolDir.isDirectory()) { - error = String.format("build-tool/%1$s folder is missing", - buildToolDir.getName()); - } else { - File[] files = buildToolDir.listFiles(); - if (files == null || files.length == 0) { - error = String.format("build-tool/%1$s folder is empty", - buildToolDir.getName()); - } else { - Set names = new HashSet(); - for (File file : files) { - names.add(file.getName()); - } - for (String name : new String[] { SdkConstants.FN_AAPT, - SdkConstants.FN_AIDL, - SdkConstants.FN_DX } ) { - if (!names.contains(name)) { - if (error == null) { - error = String.format("build-tool/%1$s folder is missing ", - buildToolDir.getName()); - } else { - error += ", "; - } - error += name; - } - } - } - } - } - - if (error == null && rev != null) { - BuildToolPackage pkg = new BuildToolPackage( - null, //source - props, - 0, //revision (extracted from props) - null, //license - null, //description - null, //descUrl - buildToolDir.getAbsolutePath()); - - if (pkg.hasCompatibleArchive()) { - return pkg; - } else { - error = "Package is not compatible with current OS"; - } - } - - - StringBuilder sb = new StringBuilder("Broken Build-Tools Package"); - if (rev != null) { - sb.append(String.format(", revision %1$s", rev.toShortString())); - } - - String shortDesc = sb.toString(); - - if (error != null) { - sb.append('\n').append(error); - } - - String longDesc = sb.toString(); - - IPkgDesc desc = PkgDesc.Builder - .newBuildTool(rev != null ? rev : new FullRevision(FullRevision.MISSING_MAJOR_REV)) - .setDescriptionShort(shortDesc) - .create(); - - return new BrokenPackage(props, shortDesc, longDesc, - IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, - IExactApiLevelDependency.API_LEVEL_INVALID, - buildToolDir.getAbsolutePath(), - desc); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected BuildToolPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - - mPkgDesc = setDescriptions(PkgDesc.Builder.newBuildTool(getRevision())).create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Returns a string identifier to install this package from the command line. - * For build-tools, we use "build-tools-" followed by the full revision string - * where spaces are changed to underscore to be more script-friendly. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return getPkgDesc().getInstallId(); - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("Android SDK Build-tools%1$s", - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("Android SDK Build-tools, revision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** Returns a long description for an {@link IDescription}. */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A build-tool package is typically installed in SDK/build-tools/revision. - * Revision spaces are replaced by underscores for ease of use in command-line. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - File folder = new File(osSdkRoot, SdkConstants.FD_BUILD_TOOLS); - StringBuilder sb = new StringBuilder(); - - PreciseRevision revision = getPkgDesc().getPreciseRevision(); - int[] version = revision.toIntArray(false); - for (int i = 0; i < version.length; i++) { - sb.append(version[i]); - if (i != version.length - 1) { - sb.append('.'); - } - } - if (getPkgDesc().getPreciseRevision().isPreview()) { - sb.append(PkgDesc.PREVIEW_SUFFIX); - } - - folder = new File(folder, sb.toString()); - return folder; - } - - /** - * Check whether 2 platform-tool packages are the same and have the - * same preview bit. - */ - @Override - public boolean sameItemAs(Package pkg) { - // Implementation note: here we don't want to care about the preview number - // so we ignore the preview when calling sameItemAs(); however we do care - // about both packages being either previews or not previews (i.e. the type - // must match but the preview number doesn't need to.) - // The end result is that a package such as "1.2 rc 4" will be an update for "1.2 rc 3". - return sameItemAs(pkg, PreviewComparison.COMPARE_TYPE); - } - - @Override - public boolean sameItemAs(Package pkg, PreviewComparison comparePreview) { - // Contrary to other package types, build-tools do not "update themselves" - // so 2 build tools with 2 different revisions are not the same item. - if (pkg instanceof BuildToolPackage) { - BuildToolPackage rhs = (BuildToolPackage) pkg; - return rhs.getRevision().compareTo(getRevision(), comparePreview) == 0; - } - return false; - } - - /** - * For build-tool package use their revision number like version numbers and - * we want them sorted from higher to lower. To do that, insert a fake revision - * number using 9999-value into the sorting key. - *

- * {@inheritDoc} - */ - @Override - protected String comparisonKey() { - String s = super.comparisonKey(); - int pos = s.indexOf("|r:"); //$NON-NLS-1$ - assert pos > 0; - - FullRevision rev = getRevision(); - String reverseSort = String.format("|rr:%1$04d.%2$04d.%3$04d.", //$NON-NLS-1$ - 9999 - rev.getMajor(), - 9999 - rev.getMinor(), - 9999 - rev.getMicro()); - - s = s.substring(0, pos) + reverseSort + s.substring(pos); - return s; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/DocPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/DocPackage.java deleted file mode 100644 index 3582f5b1..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/DocPackage.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import org.w3c.dom.Node; - -import java.io.File; -import java.util.Map; -import java.util.Properties; - -/** - * Represents a doc XML node in an SDK repository. - *

- * Note that a doc package has a version and thus implements {@link IAndroidVersionProvider}. - * However there is no mandatory dependency that limits installation so this does not - * implement {@link IPlatformDependency}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class DocPackage extends MajorRevisionPackage implements IAndroidVersionProvider { - - private final AndroidVersion mVersion; - private final IPkgDesc mPkgDesc; - - /** - * Creates a new doc package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public DocPackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - int apiLevel = - PackageParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0); - String codeName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME); - if (codeName.isEmpty()) { - codeName = null; - } - mVersion = new AndroidVersion(apiLevel, codeName); - - mPkgDesc = setDescriptions( - PkgDesc.Builder.newDoc(mVersion, (MajorRevision) getRevision())) - .create(); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create(SdkSource source, - Properties props, - int apiLevel, - String codename, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - return new DocPackage(source, props, apiLevel, codename, revision, license, description, - descUrl, archiveOsPath); - } - - private DocPackage(SdkSource source, - Properties props, - int apiLevel, - String codename, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - mVersion = new AndroidVersion(props, apiLevel, codename); - - mPkgDesc = setDescriptions(PkgDesc.Builder.newDoc(mVersion, (MajorRevision) getRevision())) - .create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be give the constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - mVersion.saveProperties(props); - } - - /** - * Returns the version, for platform, add-on and doc packages. - * Can be 0 if this is a local package of unknown api-level. - */ - @Override @NonNull - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** - * Returns a string identifier to install this package from the command line. - * For docs, we use "doc-N" where N is the API or the preview codename. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return "doc-" + mVersion.getApiString(); //$NON-NLS-1$ - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - if (mVersion.isPreview()) { - return String.format("Documentation for Android '%1$s' Preview SDK%2$s", - mVersion.getCodename(), - isObsolete() ? " (Obsolete)" : ""); - } else { - return String.format("Documentation for Android SDK%2$s", - mVersion.getApiLevel(), - isObsolete() ? " (Obsolete)" : ""); - } - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - if (mVersion.isPreview()) { - return String.format("Documentation for Android '%1$s' Preview SDK, revision %2$s%3$s", - mVersion.getCodename(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } else { - return String.format("Documentation for Android SDK, API %1$d, revision %2$s%3$s", - mVersion.getApiLevel(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A "doc" package should always be located in SDK/docs. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - return new File(osSdkRoot, SdkConstants.FD_DOCS); - } - - /** - * Consider doc packages to be the same if they cover the same API level, - * regardless of their revision number. - */ - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof DocPackage) { - AndroidVersion rev2 = ((DocPackage) pkg).getAndroidVersion(); - return this.getAndroidVersion().equals(rev2); - } - - return false; - } - - /** - * {@inheritDoc} - *


- * Doc packages are a bit different since there can only be one doc installed at - * the same time. - *

- * We now consider that docs for different APIs are NOT updates, e.g. doc for API N+1 - * is no longer considered an update for doc API N. - * However docs that have the same API version (API level + codename) are considered - * updates if they have a higher revision number (so 15 rev 2 is an update for 15 rev 1, - * but is not an update for 14 rev 1.) - */ - @Override - public UpdateInfo canBeUpdatedBy(Package replacementPackage) { - // check they are the same kind of object - if (!(replacementPackage instanceof DocPackage)) { - return UpdateInfo.INCOMPATIBLE; - } - - DocPackage replacementDoc = (DocPackage)replacementPackage; - - AndroidVersion replacementVersion = replacementDoc.getAndroidVersion(); - - // Check if they're the same exact (api and codename) - if (replacementVersion.equals(mVersion)) { - // exact same version, so check the revision level - if (replacementPackage.getRevision().compareTo(this.getRevision()) > 0) { - return UpdateInfo.UPDATE; - } - } else { - // not the same version? we check if they have the same api level and the new one - // is a preview, in which case it's also an update (since preview have the api level - // of the _previous_ version.) - if (replacementVersion.getApiLevel() == mVersion.getApiLevel() && - replacementVersion.isPreview()) { - return UpdateInfo.UPDATE; - } - } - - // not an upgrade but not incompatible either. - return UpdateInfo.NOT_UPDATE; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof DocPackage)) { - return false; - } - DocPackage other = (DocPackage) obj; - if (mVersion == null) { - if (other.mVersion != null) { - return false; - } - } else if (!mVersion.equals(other.mVersion)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ExtraPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ExtraPackage.java deleted file mode 100644 index fccbd211..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ExtraPackage.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.LocalSdkParser; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.RepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDescExtra; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.sdklib.repository.descriptors.PkgDescExtra; -import com.android.sdklib.repository.local.LocalExtraPkgInfo; -import com.android.utils.NullLogger; -import org.w3c.dom.Node; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * Represents a extra XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ExtraPackage extends NoPreviewRevisionPackage - implements IMinApiLevelDependency, IMinToolsDependency { - - /** Mixin handling the min-tools dependency. */ - private final MinToolsMixin mMinToolsMixin; - - /** - * The extra display name. Used in the UI to represent the package. It can be anything. - */ - private final String mDisplayName; - - /** - * The vendor id + name. - * The id is a simple alphanumeric string [a-zA-Z0-9_-]. - * The display name is used in the UI to represent the vendor. It can be anything. - */ - private final IdDisplay mVendor; - - /** - * The sub-folder name. It must be a non-empty single-segment path. - */ - private final String mPath; - - /** - * The optional old_paths, if any. If present, this is a list of old "path" values that - * we'd like to migrate to the current "path" name for this extra. - */ - private final String mOldPaths; - - /** - * The minimal API level required by this extra package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - private final int mMinApiLevel; - - /** - * The project-files listed by this extra package. - * The array can be empty but not null. - */ - private final String[] mProjectFiles; - - private final IPkgDescExtra mPkgDesc; - - /** - * Creates a new tool package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public ExtraPackage( - SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mMinToolsMixin = new MinToolsMixin(packageNode); - - mPath = PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_PATH); - - // Read name-display, vendor-display and vendor-id, introduced in addon-4.xsd. - // These are not optional, they are mandatory in addon-4 but we still treat them - // as optional so that we can fallback on using which was the only one - // defined in addon-3.xsd. - String name = - PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_NAME_DISPLAY); - String vname = - PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR_DISPLAY); - String vid = - PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR_ID); - - if (vid.isEmpty()) { - // If vid is missing, use the old attribute. - // Note that in a valid XML, vendor-id cannot be an empty string. - // The only reason vid can be empty is when is missing, which - // happens in an addon-3 schema, in which case the old needs to be used. - String vendor = PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR); - vid = sanitizeLegacyVendor(vendor); - if (vname.isEmpty()) { - vname = vendor; - } - } - if (vname.isEmpty()) { - // The vendor-display name can be empty, in which case we use the vendor-id. - vname = vid; - } - mVendor = new IdDisplay(vid.trim(), vname.trim()); - - if (name.isEmpty()) { - // If name is missing, use the attribute as done in an addon-3 schema. - name = LocalExtraPkgInfo.getPrettyName(mVendor, mPath); - } - mDisplayName = name.trim(); - - mMinApiLevel = PackageParserUtils.getXmlInt( - packageNode, RepoConstants.NODE_MIN_API_LEVEL, MIN_API_LEVEL_NOT_SPECIFIED); - - mProjectFiles = parseProjectFiles( - PackageParserUtils.findChildElement(packageNode, RepoConstants.NODE_PROJECT_FILES)); - - mOldPaths = PackageParserUtils.getXmlString(packageNode, RepoConstants.NODE_OLD_PATHS); - - mPkgDesc = - (IPkgDescExtra)setDescriptions(PkgDesc.Builder.newExtra(mVendor, mPath, mDisplayName, - getOldPaths(), getRevision())).create(); - } - - private String[] parseProjectFiles(Node projectFilesNode) { - ArrayList paths = new ArrayList(); - - if (projectFilesNode != null) { - String nsUri = projectFilesNode.getNamespaceURI(); - for(Node child = projectFilesNode.getFirstChild(); - child != null; - child = child.getNextSibling()) { - - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI()) && - RepoConstants.NODE_PATH.equals(child.getLocalName())) { - String path = child.getTextContent(); - if (path != null) { - path = path.trim(); - if (!path.isEmpty()) { - paths.add(path); - } - } - } - } - } - - return paths.toArray(new String[paths.size()]); - } - - /** - * Manually create a new package with one archive and the given attributes or properties. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create(SdkSource source, - Properties props, - String vendor, - String path, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - ExtraPackage ep = new ExtraPackage(source, props, vendor, path, revision, license, - description, descUrl, archiveOsPath); - return ep; - } - - /** - * Constructor used to create a mock {@link ExtraPackage}. - * Most of the attributes here are optional. - * When not defined, they will be extracted from the {@code props} properties. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected ExtraPackage(SdkSource source, - Properties props, - String vendorId, - String path, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - - mMinToolsMixin = new MinToolsMixin( - source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - - // The path argument comes before whatever could be in the properties - mPath = path != null ? path : getProperty(props, PkgProps.EXTRA_PATH, path); - - String name = getProperty(props, PkgProps.EXTRA_NAME_DISPLAY, ""); //$NON-NLS-1$ - String vname = getProperty(props, PkgProps.EXTRA_VENDOR_DISPLAY, ""); //$NON-NLS-1$ - String vid = vendorId != null ? vendorId : - getProperty(props, PkgProps.EXTRA_VENDOR_ID, ""); //$NON-NLS-1$ - - if (vid == null || vid.isEmpty()) { - // If vid is missing, use the old attribute. - // did not exist prior to schema repo-v3 and tools r8. - String vendor = getProperty(props, PkgProps.EXTRA_VENDOR, ""); //$NON-NLS-1$ - vid = sanitizeLegacyVendor(vendor); - if (vname == null || vname.isEmpty()) { - vname = vendor; - } - } - if (vname == null || vname.isEmpty()) { - // The vendor-display name can be empty, in which case we use the vendor-id. - vname = vid; - } - mVendor = new IdDisplay(vid.trim(), vname.trim()); - - if (name == null || name.isEmpty()) { - // If name is missing, use the attribute as done in an addon-3 schema. - name = LocalExtraPkgInfo.getPrettyName(mVendor, mPath); - } - mDisplayName = name.trim(); - - mOldPaths = getProperty(props, PkgProps.EXTRA_OLD_PATHS, null); - - mMinApiLevel = getPropertyInt(props, PkgProps.EXTRA_MIN_API_LEVEL, - MIN_API_LEVEL_NOT_SPECIFIED); - - String projectFiles = getProperty(props, PkgProps.EXTRA_PROJECT_FILES, null); - ArrayList filePaths = new ArrayList(); - if (projectFiles != null && !projectFiles.isEmpty()) { - for (String filePath : projectFiles.split(Pattern.quote(File.pathSeparator))) { - filePath = filePath.trim(); - if (!filePath.isEmpty()) { - filePaths.add(filePath); - } - } - } - - mProjectFiles = filePaths.toArray(new String[filePaths.size()]); - - mPkgDesc = (IPkgDescExtra) setDescriptions(PkgDesc.Builder - .newExtra(mVendor, mPath, mDisplayName, getOldPaths(), getRevision())) - .create(); - } - - @Override - @NonNull - public IPkgDescExtra getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be give the constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - mMinToolsMixin.saveProperties(props); - - props.setProperty(PkgProps.EXTRA_PATH, mPath); - props.setProperty(PkgProps.EXTRA_NAME_DISPLAY, mDisplayName); - props.setProperty(PkgProps.EXTRA_VENDOR_DISPLAY, mVendor.getDisplay()); - props.setProperty(PkgProps.EXTRA_VENDOR_ID, mVendor.getId()); - - if (getMinApiLevel() != MIN_API_LEVEL_NOT_SPECIFIED) { - props.setProperty(PkgProps.EXTRA_MIN_API_LEVEL, Integer.toString(getMinApiLevel())); - } - - if (mProjectFiles.length > 0) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < mProjectFiles.length; i++) { - if (i > 0) { - sb.append(File.pathSeparatorChar); - } - sb.append(mProjectFiles[i]); - } - props.setProperty(PkgProps.EXTRA_PROJECT_FILES, sb.toString()); - } - - if (mOldPaths != null && !mOldPaths.isEmpty()) { - props.setProperty(PkgProps.EXTRA_OLD_PATHS, mOldPaths); - } - } - - /** - * The minimal revision of the tools package required by this extra package, if > 0, - * or {@link #MIN_TOOLS_REV_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public FullRevision getMinToolsRevision() { - return mMinToolsMixin.getMinToolsRevision(); - } - - /** - * Returns the minimal API level required by this extra package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public int getMinApiLevel() { - return mMinApiLevel; - } - - /** - * The project-files listed by this extra package. - * The array can be empty but not null. - *

- * IMPORTANT: directory separators are NOT translated and may not match - * the {@link File#separatorChar} of the current platform. It's up to the - * user to adequately interpret the paths. - * Similarly, no guarantee is made on the validity of the paths. - * Users are expected to apply all usual sanity checks such as removing - * "./" and "../" and making sure these paths don't reference files outside - * of the installed archive. - * - * @since sdk-repository-4.xsd or sdk-addon-2.xsd - */ - public String[] getProjectFiles() { - return mProjectFiles; - } - - /** - * Returns the old_paths, a list of obsolete path names for the extra package. - *

- * These can be used by the installer to migrate an extra package using one of the - * old paths into the new path. - *

- * These can also be used to recognize "old" renamed packages as the same as - * the current one. - * - * @return A list of old paths. Can be empty but not null. - */ - public String[] getOldPaths() { - return PkgDescExtra.convertOldPaths(mOldPaths); - } - - /** - * Returns the sanitized path folder name. It is a single-segment path. - *

- * The package is installed in SDK/extras/vendor_name/path_name. - */ - public String getPath() { - // The XSD specifies the XML vendor and path should only contain [a-zA-Z0-9]+ - // and cannot be empty. Let's be defensive and enforce that anyway since things - // like "____" are still valid values that we don't want to allow. - - // Sanitize the path - String path = mPath.replaceAll("[^a-zA-Z0-9-]+", "_"); //$NON-NLS-1$ - if (path.isEmpty() || path.equals("_")) { //$NON-NLS-1$ - int h = path.hashCode(); - path = String.format("extra%08x", h); //$NON-NLS-1$ - } - - return path; - } - - /** - * Returns the vendor id. - */ - public String getVendorId() { - return mVendor.getId(); - } - - public String getVendorDisplay() { - return mVendor.getDisplay(); - } - - public String getDisplayName() { - return mDisplayName; - } - - /** Transforms the legacy vendor name into a usable vendor id. */ - private String sanitizeLegacyVendor(String vendorDisplay) { - // The XSD specifies the XML vendor and path should only contain [a-zA-Z0-9]+ - // and cannot be empty. Let's be defensive and enforce that anyway since things - // like "____" are still valid values that we don't want to allow. - - if (vendorDisplay != null && !vendorDisplay.isEmpty()) { - String vendor = vendorDisplay.trim(); - // Sanitize the vendor - vendor = vendor.replaceAll("[^a-zA-Z0-9-]+", "_"); //$NON-NLS-1$ - if (vendor.equals("_")) { //$NON-NLS-1$ - int h = vendor.hashCode(); - vendor = String.format("vendor%08x", h); //$NON-NLS-1$ - } - - return vendor; - } - - return ""; //$NON-NLS-1$ - - } - - /** - * Returns a string identifier to install this package from the command line. - * For extras, we use "extra-vendor-path". - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return String.format("extra-%1$s-%2$s", //$NON-NLS-1$ - getVendorId(), - getPath()); - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - String s = String.format("%1$s%2$s", - getDisplayName(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - - return s; - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - String s = String.format("%1$s, revision %2$s%3$s", - getDisplayName(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - - return s; - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = String.format("%1$s, revision %2$s%3$s\nBy %4$s", - getDisplayName(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : "", //$NON-NLS-2$ - getVendorDisplay()); - - String d = getDescription(); - if (d != null && !d.isEmpty()) { - s += '\n' + d; - } - - if (!getMinToolsRevision().equals(MIN_TOOLS_REV_NOT_SPECIFIED)) { - s += String.format("\nRequires tools revision %1$s", - getMinToolsRevision().toShortString()); - } - - if (getMinApiLevel() != MIN_API_LEVEL_NOT_SPECIFIED) { - s += String.format("\nRequires SDK Platform Android API %1$s", getMinApiLevel()); - } - - File localPath = getLocalArchivePath(); - if (localPath != null) { - // For a local archive, also put the install path in the long description. - // This should help users locate the extra on their drive. - s += String.format("\nLocation: %1$s", localPath.getAbsolutePath()); - } else { - // For a non-installed archive, indicate where it would be installed. - s += String.format("\nInstall path: %1$s", - getInstallSubFolder(null/*sdk root*/).getPath()); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A "tool" package should always be located in SDK/tools. - * - * @param osSdkRoot The OS path of the SDK root folder. Must NOT be null. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * Not used in this implementation. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - - // First find if this extra is already installed. If so, reuse the same directory. - LocalSdkParser localParser = new LocalSdkParser(); - Package[] pkgs = localParser.parseSdk( - osSdkRoot, - sdkManager, - LocalSdkParser.PARSE_EXTRAS, - new NullTaskMonitor(NullLogger.getLogger())); - - for (Package pkg : pkgs) { - if (sameItemAs(pkg) && pkg instanceof ExtraPackage) { - File localPath = ((ExtraPackage) pkg).getLocalArchivePath(); - if (localPath != null) { - return localPath; - } - } - } - - return getInstallSubFolder(osSdkRoot); - } - - /** - * Computes the "sub-folder" install path, relative to the given SDK root. - * For an extra package, this is generally ".../extra/vendor-id/path". - * - * @param osSdkRoot The OS path of the SDK root folder if known. - * This CAN be null, in which case the path will start at /extra. - * @return Either /extra/vendor/path or sdk-root/extra/vendor-id/path. - */ - private File getInstallSubFolder(@Nullable String osSdkRoot) { - // The /extras dir at the root of the SDK - File path = new File(osSdkRoot, SdkConstants.FD_EXTRAS); - - String vendor = getVendorId(); - if (vendor != null && !vendor.isEmpty()) { - path = new File(path, vendor); - } - - String name = getPath(); - if (name != null && !name.isEmpty()) { - path = new File(path, name); - } - - return path; - } - - @Override - public boolean sameItemAs(Package pkg) { - // Extra packages are similar if they have the same path and vendor - if (pkg instanceof ExtraPackage) { - ExtraPackage ep = (ExtraPackage) pkg; - return PkgDescExtra.compatibleVendorAndPath(mPkgDesc, ep.mPkgDesc); - } - - return false; - } - - /** - * For extra packages, we want to add vendor|path to the sorting key - * before the revision number. - *

- * {@inheritDoc} - */ - @Override - protected String comparisonKey() { - String s = super.comparisonKey(); - int pos = s.indexOf("|r:"); //$NON-NLS-1$ - assert pos > 0; - s = s.substring(0, pos) + - "|ve:" + getVendorId() + //$NON-NLS-1$ - "|pa:" + getPath() + //$NON-NLS-1$ - s.substring(pos); - return s; - } - - // --- - - /** - * If this package is installed, returns the install path of the archive if valid. - * Returns null if not installed or if the path does not exist. - */ - private File getLocalArchivePath() { - Archive[] archives = getArchives(); - if (archives.length == 1 && archives[0].isLocal()) { - File path = new File(archives[0].getLocalOsPath()); - if (path.isDirectory()) { - return path; - } - } - - return null; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = mMinToolsMixin.hashCode(super.hashCode()); - result = prime * result + mMinApiLevel; - result = prime * result + ((mPath == null) ? 0 : mPath.hashCode()); - result = prime * result + Arrays.hashCode(mProjectFiles); - result = prime * result + ((mVendor == null) ? 0 : mVendor.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof ExtraPackage)) { - return false; - } - ExtraPackage other = (ExtraPackage) obj; - if (mMinApiLevel != other.mMinApiLevel) { - return false; - } - if (mPath == null) { - if (other.mPath != null) { - return false; - } - } else if (!mPath.equals(other.mPath)) { - return false; - } - if (!Arrays.equals(mProjectFiles, other.mProjectFiles)) { - return false; - } - if (mVendor == null) { - if (other.mVendor != null) { - return false; - } - } else if (!mVendor.equals(other.mVendor)) { - return false; - } - return mMinToolsMixin.equals(obj); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java deleted file mode 100644 index 5e9b6316..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository.packages; - -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Node; - -import java.util.Map; -import java.util.Properties; - -/** - * Represents a package in an SDK repository that has a {@link FullRevision}, - * which is a multi-part revision number (major.minor.micro) and an optional preview revision. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class FullRevisionPackage extends Package - implements IFullRevisionProvider { - - private final FullRevision mPreviewVersion; - - /** - * Creates a new package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - FullRevisionPackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mPreviewVersion = PackageParserUtils.parseFullRevisionElement( - PackageParserUtils.findChildElement(packageNode, SdkRepoConstants.NODE_REVISION)); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public FullRevisionPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, props, revision, license, description, descUrl, archiveOsPath); - - FullRevision rev = PackageParserUtils.getPropertyFull(props, PkgProps.PKG_REVISION); - if (rev == null) { - rev = new FullRevision(revision); - } - mPreviewVersion = rev; - } - - @Override - public FullRevision getRevision() { - return mPreviewVersion; - } - - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - props.setProperty(PkgProps.PKG_REVISION, mPreviewVersion.toShortString()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mPreviewVersion == null) ? 0 : mPreviewVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof FullRevisionPackage)) { - return false; - } - FullRevisionPackage other = (FullRevisionPackage) obj; - if (mPreviewVersion == null) { - if (other.mPreviewVersion != null) { - return false; - } - } else if (!mPreviewVersion.equals(other.mPreviewVersion)) { - return false; - } - return true; - } - - /** - * Computes whether the given package is a suitable update for the current package. - *

- * A specific case here is that a release package can update a preview, whereas - * a preview can only update another preview. - *

- * {@inheritDoc} - */ - @Override - public UpdateInfo canBeUpdatedBy(Package replacementPackage) { - if (replacementPackage == null) { - return UpdateInfo.INCOMPATIBLE; - } - - // check they are the same item, ignoring the preview bit. - if (!sameItemAs(replacementPackage, PreviewComparison.IGNORE)) { - return UpdateInfo.INCOMPATIBLE; - } - - // a preview cannot update a non-preview - if (!getRevision().isPreview() && replacementPackage.getRevision().isPreview()) { - return UpdateInfo.INCOMPATIBLE; - } - - // check revision number - if (replacementPackage.getRevision().compareTo(this.getRevision()) > 0) { - return UpdateInfo.UPDATE; - } - - // not an upgrade but not incompatible either. - return UpdateInfo.NOT_UPDATE; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IAndroidVersionProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IAndroidVersionProvider.java deleted file mode 100644 index 0f1a53f0..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IAndroidVersionProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; - -/** - * Interface for packages that provide an {@link AndroidVersion}. - *

- * Note that {@link IPlatformDependency} is a similar interface, but with a different semantic. - * The {@link IPlatformDependency} denotes that a given package can only be installed if the - * requested platform is present, whereas this interface denotes that the given package simply - * has a version, which is not necessarily a dependency. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IAndroidVersionProvider { - - /** - * Returns the android version, for platform, add-on and doc packages. - * Can be 0 if this is a local package of unknown api-level. - */ - @NonNull - AndroidVersion getAndroidVersion(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IExactApiLevelDependency.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IExactApiLevelDependency.java deleted file mode 100644 index 7ed20659..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IExactApiLevelDependency.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.packages; - -import com.android.sdklib.repository.RepoConstants; - -/** - * Interface used to decorate a {@link Package} that has a dependency - * on a specific API level, e.g. which XML has a {@code } element. - *

- * For example an add-on package requires a platform with an exact API level to be installed - * at the same time. - * This is not the same as {@link IMinApiLevelDependency} which requests that a platform with at - * least the requested API level be present or installed at the same time. - *

- * Such package requires the {@code } element. It is not an optional - * property, however it can be invalid. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IExactApiLevelDependency { - - /** - * The value of {@link #getExactApiLevel()} when the {@link RepoConstants#NODE_API_LEVEL} - * was not specified in the XML source. - */ - int API_LEVEL_INVALID = 0; - - /** - * Returns the exact API level required by this package, if > 0, - * or {@link #API_LEVEL_INVALID} if the value was missing. - *

- * This attribute is mandatory and should not be normally missing. - * It can only happen when dealing with an invalid repository XML. - */ - int getExactApiLevel(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IFullRevisionProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IFullRevisionProvider.java deleted file mode 100644 index 6da200cb..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IFullRevisionProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository.packages; - -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; - - - -/** - * Interface for packages that provide a {@link FullRevision}, - * which is a multi-part revision number (major.minor.micro) and an optional preview revision. - *

- * This interface is a tag. It indicates that {@link Package#getRevision()} returns a - * {@link FullRevision} instead of a limited {@link MajorRevision}.
- * The preview version number is available via {@link Package#getRevision()}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IFullRevisionProvider { - - /** - * Returns whether the given package represents the same item as the current package. - *

- * Two packages are considered the same if they represent the same thing, except for the - * revision number. - * @param pkg The package to compare - * @param comparePreview How to compare previews. - * @return true if the items are the same. - */ - boolean sameItemAs(Package pkg, PreviewComparison comparePreview); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ILayoutlibVersion.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ILayoutlibVersion.java deleted file mode 100644 index 30b2112d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ILayoutlibVersion.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.packages; - -import com.android.utils.Pair; - -/** - * Interface used to decorate a {@link Package} that provides a version for layout lib. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface ILayoutlibVersion { - - int LAYOUTLIB_API_NOT_SPECIFIED = 0; - int LAYOUTLIB_REV_NOT_SPECIFIED = 0; - - /** - * Returns the layoutlib version. Mandatory starting with repository XSD rev 4. - *

- * The first integer is the API of layoublib, which should be > 0. - * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib - * version isn't specified. - *

- * The second integer is the revision for that given API. It is >= 0 - * and works as a minor revision number, incremented for the same API level. - * - * @since sdk-repository-4.xsd - */ - Pair getLayoutlibVersion(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinApiLevelDependency.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinApiLevelDependency.java deleted file mode 100644 index 60e6d344..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinApiLevelDependency.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.sdklib.repository.SdkRepoConstants; - -/** - * Interface used to decorate a {@link Package} that has a dependency - * on a minimal API level, e.g. which XML has a <min-api-level> element. - *

- * A package that has this dependency can only be installed if a platform with at least the - * requested API level is present or installed at the same time. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IMinApiLevelDependency { - - /** - * The value of {@link #getMinApiLevel()} when the {@link SdkRepoConstants#NODE_MIN_API_LEVEL} - * was not specified in the XML source. - */ - int MIN_API_LEVEL_NOT_SPECIFIED = 0; - - /** - * Returns the minimal API level required by this package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - int getMinApiLevel(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinPlatformToolsDependency.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinPlatformToolsDependency.java deleted file mode 100644 index 49c84f81..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinPlatformToolsDependency.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.SdkRepoConstants; - -/** - * Interface used to decorate a {@link Package} that has a dependency - * on a minimal platform-tools revision, e.g. which XML has a - * <min-platform-tools-rev> element. - *

- * A package that has this dependency can only be installed if the requested platform-tools - * revision is present or installed at the same time. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IMinPlatformToolsDependency { - - /** - * The value of {@link #getMinPlatformToolsRevision()} when the - * {@link SdkRepoConstants#NODE_MIN_PLATFORM_TOOLS_REV} was not specified in the XML source. - * Since this is a required attribute in the XML schema, it can only happen when dealing - * with an invalid repository XML. - */ - FullRevision MIN_PLATFORM_TOOLS_REV_INVALID = - new FullRevision(FullRevision.MISSING_MAJOR_REV); - - /** - * The minimal revision of the tools package required by this package if > 0, - * or {@link #MIN_PLATFORM_TOOLS_REV_INVALID} if the value was missing. - *

- * This attribute is mandatory and should not be normally missing. - * It can only happen when dealing with an invalid repository XML. - */ - FullRevision getMinPlatformToolsRevision(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinToolsDependency.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinToolsDependency.java deleted file mode 100644 index ebdbf591..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IMinToolsDependency.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.SdkRepoConstants; - -/** - * Interface used to decorate a {@link Package} that has a dependency - * on a minimal tools revision, e.g. which XML has a <min-tools-rev> element. - *

- * A package that has this dependency can only be installed if the requested tools revision - * is present or installed at the same time. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IMinToolsDependency { - - /** - * The value of {@link #getMinToolsRevision()} when the - * {@link SdkRepoConstants#NODE_MIN_TOOLS_REV} was not specified in the XML source. - */ - FullRevision MIN_TOOLS_REV_NOT_SPECIFIED = - new FullRevision(FullRevision.MISSING_MAJOR_REV); - - /** - * The minimal revision of the tools package required by this extra package if > 0, - * or {@link #MIN_TOOLS_REV_NOT_SPECIFIED} if there is no such requirement. - */ - FullRevision getMinToolsRevision(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IPlatformDependency.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IPlatformDependency.java deleted file mode 100644 index ccbb267c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/IPlatformDependency.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.sdklib.AndroidVersion; - -/** - * Interface used to decorate a {@link Package} that has a dependency - * on a specific platform (API level and/or code name). - *

- * A package that has this dependency can only be installed if a platform with at least the - * requested API level is present or installed at the same time. - *

- * Note that although this interface looks like {@link IAndroidVersionProvider}, it does - * not convey the same semantic since {@link IAndroidVersionProvider} does not - * imply any dependency being a limiting factor as far as installation is concerned. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IPlatformDependency { - - /** Returns the version of the platform dependency of this package. */ - AndroidVersion getAndroidVersion(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/LayoutlibVersionMixin.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/LayoutlibVersionMixin.java deleted file mode 100644 index 7d18edaa..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/LayoutlibVersionMixin.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.packages; - -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.RepoConstants; -import com.android.utils.Pair; - -import org.w3c.dom.Node; - -import java.util.Properties; - -/** - * Helper class to handle the layoutlib version provided by a package. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class LayoutlibVersionMixin implements ILayoutlibVersion { - - /** - * The layoutlib version. - * The first integer is the API of layoublib, which should be > 0. - * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib - * version isn't specified. - * The second integer is the revision for that given API. It is >= 0 - * and works as a minor revision number, incremented for the same API level. - */ - private final Pair mLayoutlibVersion; - - /** - * Parses an XML node to process the {@code } element. - * - * The layoutlib element is new in the XSD rev 4, so we need to cope with it missing - * in earlier XMLs. - */ - public LayoutlibVersionMixin(Node pkgNode) { - - int api = LAYOUTLIB_API_NOT_SPECIFIED; - int rev = LAYOUTLIB_REV_NOT_SPECIFIED; - - Node layoutlibNode = - PackageParserUtils.findChildElement(pkgNode, RepoConstants.NODE_LAYOUT_LIB); - - if (layoutlibNode != null) { - api = PackageParserUtils.getXmlInt(layoutlibNode, RepoConstants.NODE_API, 0); - rev = PackageParserUtils.getXmlInt(layoutlibNode, RepoConstants.NODE_REVISION, 0); - } - - mLayoutlibVersion = Pair.of(api, rev); - } - - /** - * Parses the layoutlib version optionally available in the given {@link Properties}. - */ - public LayoutlibVersionMixin(Properties props) { - int layoutlibApi = Package.getPropertyInt(props, PkgProps.LAYOUTLIB_API, - LAYOUTLIB_API_NOT_SPECIFIED); - int layoutlibRev = Package.getPropertyInt(props, PkgProps.LAYOUTLIB_REV, - LAYOUTLIB_REV_NOT_SPECIFIED); - mLayoutlibVersion = Pair.of(layoutlibApi, layoutlibRev); - } - - /** - * Stores the layoutlib version in the given {@link Properties}. - */ - void saveProperties(Properties props) { - if (mLayoutlibVersion.getFirst().intValue() != LAYOUTLIB_API_NOT_SPECIFIED) { - props.setProperty(PkgProps.LAYOUTLIB_API, mLayoutlibVersion.getFirst().toString()); - props.setProperty(PkgProps.LAYOUTLIB_REV, mLayoutlibVersion.getSecond().toString()); - } - } - - /** - * Returns the layoutlib version. - *

- * The first integer is the API of layoublib, which should be > 0. - * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib - * version isn't specified. - *

- * The second integer is the revision for that given API. It is >= 0 - * and works as a minor revision number, incremented for the same API level. - * - * @since sdk-repository-4.xsd and sdk-addon-2.xsd - */ - @Override - public Pair getLayoutlibVersion() { - return mLayoutlibVersion; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mLayoutlibVersion == null) ? 0 : mLayoutlibVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof LayoutlibVersionMixin)) { - return false; - } - LayoutlibVersionMixin other = (LayoutlibVersionMixin) obj; - if (mLayoutlibVersion == null) { - if (other.mLayoutlibVersion != null) { - return false; - } - } else if (!mLayoutlibVersion.equals(other.mLayoutlibVersion)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java deleted file mode 100644 index 38bc3a0e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository.packages; - -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Node; - -import java.util.Map; -import java.util.Properties; - -/** - * Represents a package in an SDK repository that has a {@link MajorRevision}, - * which is a single major revision number (not minor, micro or previews). - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class MajorRevisionPackage extends Package { - - private final MajorRevision mRevision; - - /** - * Creates a new package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - MajorRevisionPackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mRevision = new MajorRevision( - PackageParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_REVISION, 0)); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public MajorRevisionPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, props, revision, license, description, descUrl, archiveOsPath); - - String revStr = getProperty(props, PkgProps.PKG_REVISION, null); - - MajorRevision rev = null; - if (revStr != null) { - try { - rev = MajorRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - if (rev == null) { - rev = new MajorRevision(revision); - } - - mRevision = rev; - } - - /** - * Returns the revision, an int > 0, for all packages (platform, add-on, tool, doc). - * Can be 0 if this is a local package of unknown revision. - */ - @Override - public FullRevision getRevision() { - return mRevision; - } - - - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - props.setProperty(PkgProps.PKG_REVISION, mRevision.toString()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mRevision == null) ? 0 : mRevision.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof MajorRevisionPackage)) { - return false; - } - MajorRevisionPackage other = (MajorRevisionPackage) obj; - if (mRevision == null) { - if (other.mRevision != null) { - return false; - } - } else if (!mRevision.equals(other.mRevision)) { - return false; - } - return true; - } - - @Override - public UpdateInfo canBeUpdatedBy(Package replacementPackage) { - if (replacementPackage == null) { - return UpdateInfo.INCOMPATIBLE; - } - - // check they are the same item. - if (!sameItemAs(replacementPackage)) { - return UpdateInfo.INCOMPATIBLE; - } - - // check revision number - if (replacementPackage.getRevision().compareTo(this.getRevision()) > 0) { - return UpdateInfo.UPDATE; - } - - // not an upgrade but not incompatible either. - return UpdateInfo.NOT_UPDATE; - } - - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsMixin.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsMixin.java deleted file mode 100644 index b85ba8a8..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsMixin.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2013 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.internal.repository.packages; - -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Node; - -import java.util.Properties; - -/** - * Represents an XML node in an SDK repository that has a min-tools-rev requirement. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -class MinToolsMixin implements IMinToolsDependency { - - /** - * The minimal revision of the tools package required by this extra package, if > 0, - * or {@link #MIN_TOOLS_REV_NOT_SPECIFIED} if there is no such requirement. - */ - private final FullRevision mMinToolsRevision; - - /** - * Creates a new mixin from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param packageNode The XML element being parsed. - */ - MinToolsMixin(Node packageNode) { - - mMinToolsRevision = PackageParserUtils.parseFullRevisionElement( - PackageParserUtils.findChildElement(packageNode, SdkRepoConstants.NODE_MIN_TOOLS_REV)); - } - - /** - * Manually create a new mixin with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public MinToolsMixin( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - - String revStr = Package.getProperty(props, PkgProps.MIN_TOOLS_REV, null); - - FullRevision rev = MIN_TOOLS_REV_NOT_SPECIFIED; - if (revStr != null) { - try { - rev = FullRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - mMinToolsRevision = rev; - } - - /** - * The minimal revision of the tools package required by this extra package, if > 0, - * or {@link #MIN_TOOLS_REV_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public FullRevision getMinToolsRevision() { - return mMinToolsRevision; - } - - public void saveProperties(Properties props) { - if (!getMinToolsRevision().equals(MIN_TOOLS_REV_NOT_SPECIFIED)) { - props.setProperty(PkgProps.MIN_TOOLS_REV, getMinToolsRevision().toShortString()); - } - } - - @Override - public int hashCode() { - return hashCode(super.hashCode()); - } - - int hashCode(int superHashCode) { - final int prime = 31; - int result = superHashCode; - result = prime * result + ((mMinToolsRevision == null) ? 0 : mMinToolsRevision.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof IMinToolsDependency)) { - return false; - } - IMinToolsDependency other = (IMinToolsDependency) obj; - if (mMinToolsRevision == null) { - if (other.getMinToolsRevision() != null) { - return false; - } - } else if (!mMinToolsRevision.equals(other.getMinToolsRevision())) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsPackage.java deleted file mode 100644 index 8ea682af..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/MinToolsPackage.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; - -import org.w3c.dom.Node; - -import java.util.Map; -import java.util.Properties; - -/** - * Represents an XML node in an SDK repository that has a min-tools-rev requirement. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class MinToolsPackage extends MajorRevisionPackage implements IMinToolsDependency { - - private final MinToolsMixin mMinToolsMixin; - - /** - * Creates a new package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - MinToolsPackage(SdkSource source, Node packageNode, String nsUri, Map licenses) { - super(source, packageNode, nsUri, licenses); - - mMinToolsMixin = new MinToolsMixin(packageNode); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public MinToolsPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, props, revision, license, description, descUrl, archiveOsPath); - - mMinToolsMixin = new MinToolsMixin( - source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - } - - /** - * The minimal revision of the tools package required by this extra package, if > 0, - * or {@link #MIN_TOOLS_REV_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public FullRevision getMinToolsRevision() { - return mMinToolsMixin.getMinToolsRevision(); - } - - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - mMinToolsMixin.saveProperties(props); - } - - @Override - public int hashCode() { - return mMinToolsMixin.hashCode(super.hashCode()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof MinToolsPackage)) { - return false; - } - return mMinToolsMixin.equals(obj); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/NoPreviewRevisionPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/NoPreviewRevisionPackage.java deleted file mode 100644 index fc5a5dd1..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/NoPreviewRevisionPackage.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2013 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.internal.repository.packages; - -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Node; - -import java.util.Map; -import java.util.Properties; - -/** - * Represents a package in an SDK repository that has a {@link NoPreviewRevision}, - * which is a single major.minor.micro revision number and no preview. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class NoPreviewRevisionPackage extends Package { - - private final NoPreviewRevision mRevision; - - /** - * Creates a new package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - NoPreviewRevisionPackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mRevision = PackageParserUtils.parseNoPreviewRevisionElement( - PackageParserUtils.findChildElement(packageNode, SdkRepoConstants.NODE_REVISION)); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public NoPreviewRevisionPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, props, revision, license, description, descUrl, archiveOsPath); - - String revStr = getProperty(props, PkgProps.PKG_REVISION, null); - - NoPreviewRevision rev = null; - if (revStr != null) { - try { - rev = NoPreviewRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - if (rev == null) { - rev = new NoPreviewRevision(revision); - } - - mRevision = rev; - } - - /** - * Returns the revision, an int > 0, for all packages (platform, add-on, tool, doc). - * Can be 0 if this is a local package of unknown revision. - */ - @Override - public NoPreviewRevision getRevision() { - return mRevision; - } - - - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - props.setProperty(PkgProps.PKG_REVISION, mRevision.toString()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mRevision == null) ? 0 : mRevision.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof NoPreviewRevisionPackage)) { - return false; - } - NoPreviewRevisionPackage other = (NoPreviewRevisionPackage) obj; - if (mRevision == null) { - if (other.mRevision != null) { - return false; - } - } else if (!mRevision.equals(other.mRevision)) { - return false; - } - return true; - } - - @Override - public UpdateInfo canBeUpdatedBy(Package replacementPackage) { - if (replacementPackage == null) { - return UpdateInfo.INCOMPATIBLE; - } - - // check they are the same item. - if (!sameItemAs(replacementPackage)) { - return UpdateInfo.INCOMPATIBLE; - } - - // check revision number - if (replacementPackage.getRevision().compareTo(this.getRevision()) > 0) { - return UpdateInfo.UPDATE; - } - - // not an upgrade but not incompatible either. - return UpdateInfo.NOT_UPDATE; - } - - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/Package.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/Package.java deleted file mode 100644 index 4cf6f9b6..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/Package.java +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.IListDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkAddonSource; -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.*; -import com.android.sdklib.repository.descriptors.IPkgDesc; - -import com.android.sdklib.repository.descriptors.PkgDesc; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.w3c.dom.Node; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import java.util.Properties; - -/** - * A {@link Package} is the base class for "something" that can be downloaded from - * the SDK repository. - *

- * A package has some attributes (revision, description) and a list of archives - * which represent the downloadable bits. - *

- * Packages are contained by a {@link SdkSource} (a download site). - *

- * Derived classes must implement the {@link IDescription} methods. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class Package implements IDescription, IListDescription, Comparable { - - private final String mObsolete; - private final License mLicense; - private final String mListDisplay; - private final String mDescription; - private final String mDescUrl; - @Deprecated - private final String mReleaseNote; - @Deprecated - private final String mReleaseUrl; - private final Archive[] mArchives; - private final SdkSource mSource; - - - // figure if we'll need to set the unix permissions - private static final boolean sUsingUnixPerm = - SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN || - SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX; - - /** - * Enum for the result of {@link Package#canBeUpdatedBy(Package)}. This used so that we can - * differentiate between a package that is totally incompatible, and one that is the same item - * but just not an update. - * @see #canBeUpdatedBy(Package) - */ - public enum UpdateInfo { - /** Means that the 2 packages are not the same thing */ - INCOMPATIBLE, - /** Means that the 2 packages are the same thing but one does not upgrade the other. - *

- * TODO: this name is confusing. We need to dig deeper. */ - NOT_UPDATE, - /** Means that the 2 packages are the same thing, and one is the upgrade of the other */ - UPDATE - } - - /** - * Creates a new package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - Package(SdkSource source, Node packageNode, String nsUri, Map licenses) { - mSource = source; - mListDisplay = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_LIST_DISPLAY); - mDescription = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_DESCRIPTION); - mDescUrl = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_DESC_URL); - mReleaseNote = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_RELEASE_NOTE); - mReleaseUrl = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_RELEASE_URL); - mObsolete = - PackageParserUtils.getOptionalXmlString(packageNode, SdkRepoConstants.NODE_OBSOLETE); - - mLicense = parseLicense(packageNode, licenses); - mArchives = parseArchives( - PackageParserUtils.findChildElement(packageNode, SdkRepoConstants.NODE_ARCHIVES)); - } - - /** - * Manually create a new package with one archive and the given attributes. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * Properties from props are used first when possible, e.g. if props is non null. - *

- * By design, this creates a package with one and only one archive. - */ - public Package( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - - if (description == null) { - description = ""; - } - if (descUrl == null) { - descUrl = ""; - } - - license = getProperty(props, PkgProps.PKG_LICENSE, license); - if (license != null) { - mLicense = new License(license, getProperty(props, PkgProps.PKG_LICENSE_REF, null)); - } - else { - mLicense = null; - } - mListDisplay = getProperty(props, PkgProps.PKG_LIST_DISPLAY, ""); //$NON-NLS-1$ - mDescription = getProperty(props, PkgProps.PKG_DESC, description); - mDescUrl = getProperty(props, PkgProps.PKG_DESC_URL, descUrl); - mReleaseNote = getProperty(props, PkgProps.PKG_RELEASE_NOTE, ""); //$NON-NLS-1$ - mReleaseUrl = getProperty(props, PkgProps.PKG_RELEASE_URL, ""); //$NON-NLS-1$ - mObsolete = getProperty(props, PkgProps.PKG_OBSOLETE, null); - - // If source is null and we can find a source URL in the properties, generate - // a dummy source just to store the URL. This allows us to easily remember where - // a package comes from. - String srcUrl = getProperty(props, PkgProps.PKG_SOURCE_URL, null); - if (props != null && source == null && srcUrl != null) { - // Both Addon and Extra packages can come from an addon source. - // For Extras, we can tell by looking at the source URL. - if (this instanceof AddonPackage || - ((this instanceof ExtraPackage) && - srcUrl.endsWith(SdkAddonConstants.URL_DEFAULT_FILENAME))) { - source = new SdkAddonSource(srcUrl, null /*uiName*/); - } else { - source = new SdkRepoSource(srcUrl, null /*uiName*/); - } - } - mSource = source; - - // Note: if archiveOsPath is non-null, this makes a local archive (e.g. a locally - // installed package.) If it's null, this makes a remote archive. - mArchives = initializeArchives(props, archiveOsPath); - } - - /** - * Returns the {@link IPkgDesc} describing this package's meta data. - * - * @return A non-null {@link IPkgDesc}. - */ - @NonNull - public abstract IPkgDesc getPkgDesc(); - - /** - * Called by the constructor to get the initial {@link #mArchives} array. - *

- * This is invoked by the local-package constructor and allows mock testing - * classes to override the archives created. - * This is an implementation details and clients must not - * rely on this. - * - * @return Always return a non-null array. The array may be empty. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Archive[] initializeArchives( - Properties props, - String archiveOsPath) { - return new Archive[] { - new Archive(this, - props, - archiveOsPath) }; - } - - /** - * Utility method that returns a property from a {@link Properties} object. - * Returns the default value if props is null or if the property is not defined. - * - * @param props The {@link Properties} to search into. - * If null, the default value is returned. - * @param propKey The name of the property. Must not be null. - * @param defaultValue The default value to return if {@code props} is null or if the - * key is not found. Can be null. - * @return The string value of the given key in the properties, or null if the key - * isn't found or if {@code props} is null. - */ - @Nullable - static String getProperty( - @Nullable Properties props, - @NonNull String propKey, - @Nullable String defaultValue) { - return PackageParserUtils.getProperty(props, propKey, defaultValue); - } - - /** - * Utility method that returns an integer property from a {@link Properties} object. - * Returns the default value if props is null or if the property is not defined or - * cannot be parsed to an integer. - * - * @param props The {@link Properties} to search into. - * If null, the default value is returned. - * @param propKey The name of the property. Must not be null. - * @param defaultValue The default value to return if {@code props} is null or if the - * key is not found. Can be null. - * @return The integer value of the given key in the properties, or the {@code defaultValue}. - */ - static int getPropertyInt( - @Nullable Properties props, - @NonNull String propKey, - int defaultValue) { - return PackageParserUtils.getPropertyInt(props, propKey, defaultValue); - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be give the constructor that takes a {@link Properties} object. - */ - public void saveProperties(@NonNull Properties props) { - if (mLicense != null) { - String license = mLicense.getLicense(); - if (license != null && !license.isEmpty()) { - props.setProperty(PkgProps.PKG_LICENSE, license); - } - String licenseRef = mLicense.getLicenseRef(); - if (licenseRef != null && !licenseRef.isEmpty()) { - props.setProperty(PkgProps.PKG_LICENSE_REF, licenseRef); - } - } - if (mListDisplay != null && !mListDisplay.isEmpty()) { - props.setProperty(PkgProps.PKG_LIST_DISPLAY, mListDisplay); - } - if (mDescription != null && !mDescription.isEmpty()) { - props.setProperty(PkgProps.PKG_DESC, mDescription); - } - if (mDescUrl != null && !mDescUrl.isEmpty()) { - props.setProperty(PkgProps.PKG_DESC_URL, mDescUrl); - } - - if (mReleaseNote != null && !mReleaseNote.isEmpty()) { - props.setProperty(PkgProps.PKG_RELEASE_NOTE, mReleaseNote); - } - if (mReleaseUrl != null && !mReleaseUrl.isEmpty()) { - props.setProperty(PkgProps.PKG_RELEASE_URL, mReleaseUrl); - } - if (mObsolete != null) { - props.setProperty(PkgProps.PKG_OBSOLETE, mObsolete); - } - if (mSource != null) { - props.setProperty(PkgProps.PKG_SOURCE_URL, mSource.getUrl()); - } - } - - /** - * Parses the uses-licence node of this package, if any, and returns the license - * definition if there's one. Returns null if there's no uses-license element or no - * license of this name defined. - */ - @Nullable - private License parseLicense(@NonNull Node packageNode, @NonNull Map licenses) { - Node usesLicense = - PackageParserUtils.findChildElement(packageNode, SdkRepoConstants.NODE_USES_LICENSE); - if (usesLicense != null) { - Node ref = usesLicense.getAttributes().getNamedItem(SdkRepoConstants.ATTR_REF); - if (ref != null) { - String licenseRef = ref.getNodeValue(); - return new License(licenses.get(licenseRef), licenseRef); - } - } - return null; - } - - /** - * Parses an XML node to process the element. - * Always return a non-null array. The array may be empty. - */ - @NonNull - private Archive[] parseArchives(@NonNull Node archivesNode) { - ArrayList archives = new ArrayList(); - - if (archivesNode != null) { - String nsUri = archivesNode.getNamespaceURI(); - for(Node child = archivesNode.getFirstChild(); - child != null; - child = child.getNextSibling()) { - - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI()) && - SdkRepoConstants.NODE_ARCHIVE.equals(child.getLocalName())) { - archives.add(parseArchive(child)); - } - } - } - - return archives.toArray(new Archive[archives.size()]); - } - - /** - * Parses one element from an container. - */ - @NonNull - private Archive parseArchive(@NonNull Node archiveNode) { - Archive a = new Archive( - this, - PackageParserUtils.parseArchFilter(archiveNode), - PackageParserUtils.getXmlString(archiveNode, SdkRepoConstants.NODE_URL), - PackageParserUtils.getXmlLong (archiveNode, SdkRepoConstants.NODE_SIZE, 0), - PackageParserUtils.getXmlString(archiveNode, SdkRepoConstants.NODE_CHECKSUM) - ); - - return a; - } - - /** - * Returns the source that created (and owns) this package. Can be null. - */ - @Nullable - public SdkSource getParentSource() { - return mSource; - } - - /** - * Returns true if the package is deemed obsolete, that is it contains an - * actual <obsolete> element. - */ - public boolean isObsolete() { - return mObsolete != null; - } - - /** - * Returns the revision, an int > 0, for all packages (platform, add-on, tool, doc). - * Can be 0 if this is a local package of unknown revision. - */ - @NonNull - public abstract FullRevision getRevision(); - - /** - * Returns the optional description for all packages (platform, add-on, tool, doc) or - * for a lib. It is null if the element has not been specified in the repository XML. - */ - @Nullable - public License getLicense() { - return mLicense; - } - - /** - * Returns the optional description for all packages (platform, add-on, tool, doc) or - * for a lib. This is the raw description available from the XML meta data and is typically - * only used internally. - *

- * For actual display in the UI, use the methods from {@link IDescription} instead. - *

- * Can be empty but not null. - */ - @NonNull - public String getDescription() { - return mDescription; - } - - /** - * Returns the optional list-display for all packages as defined in the XML meta data - * and is typically only used internally. - *

- * For actual display in the UI, use {@link IListDescription} instead. - *

- * Can be empty but not null. - */ - @NonNull - public String getListDisplay() { - return mListDisplay; - } - - /** - * Returns the optional description URL for all packages (platform, add-on, tool, doc). - * Can be empty but not null. - */ - @NonNull - public String getDescUrl() { - return mDescUrl; - } - - /** - * Returns the optional release note for all packages (platform, add-on, tool, doc) or - * for a lib. Can be empty but not null. - */ - @NonNull - public String getReleaseNote() { - return mReleaseNote; - } - - /** - * Returns the optional release note URL for all packages (platform, add-on, tool, doc). - * Can be empty but not null. - */ - @NonNull - public String getReleaseNoteUrl() { - return mReleaseUrl; - } - - /** - * Returns the archives defined in this package. - * Can be an empty array but not null. - */ - @NonNull - public Archive[] getArchives() { - return mArchives; - } - - /** - * Returns true if this package contains the exact given archive. - * Important: This compares object references, not object equality. - */ - public boolean hasArchive(Archive archive) { - for (Archive a : mArchives) { - if (a == archive) { - return true; - } - } - return false; - } - - /** - * Returns whether the {@link Package} has at least one {@link Archive} compatible with - * the host platform. - */ - public boolean hasCompatibleArchive() { - for (Archive archive : mArchives) { - if (archive.isCompatible()) { - return true; - } - } - - return false; - } - - /** - * Returns a short, reasonably unique string identifier that can be used - * to identify this package when installing from the command-line interface. - * {@code 'android list sdk'} will show these IDs and then in turn they can - * be provided to {@code 'android update sdk --no-ui --filter'} to select - * some specific packages. - *

- * The identifiers must have the following properties:
- * - They must contain only simple alphanumeric characters.
- * - Commas, whitespace and any special character that could be obviously problematic - * to a shell interface should be avoided (so dash/underscore are OK, but things - * like colon, pipe or dollar should be avoided.)
- * - The name must be consistent across calls and reasonably unique for the package - * type. Collisions can occur but should be rare.
- * - Different package types should have a clearly different name pattern.
- * - The revision number should not be included, as this would prevent updates - * from being automated (which is the whole point.)
- * - It must remain reasonably human readable.
- * - If no such id can exist (for example for a local package that cannot be installed) - * then an empty string should be returned. Don't return null. - *

- * Important: This is not a strong unique identifier for the package. - * If you need a strong unique identifier, you should use {@link #comparisonKey()} - * and the {@link Comparable} interface. - */ - @NonNull - public abstract String installId(); - - /** - * Returns the short description of the source, if not null. - * Otherwise returns the default Object toString result. - *

- * This is mostly helpful for debugging. - * For UI display, use the {@link IDescription} interface. - */ - @NonNull - @Override - public String toString() { - String s = getShortDescription(); - if (s != null) { - return s; - } - return super.toString(); - } - - /** - * Returns a description of this package that is suitable for a list display. - * Should not be empty. Can never be null. - *

- * Derived classes should use {@link #getListDisplay()} if it's not empty. - *

- * When it is empty, the default behavior is to recompute a string that depends - * on the package type. - *

- * In both cases, the string should indicate whether the package is marked as obsolete. - *

- * Note that this is the "base" name for the package with no specific revision nor API - * mentioned as this is likely used in a table that will already provide these details. - * In contrast, {@link #getShortDescription()} should be used if you want more details - * such as the package revision number or the API, if applicable, all in the same string. - */ - @NonNull - @Override - public abstract String getListDescription(); - - /** - * Returns a short description for an {@link IDescription}. - * Can be empty but not null. - */ - @NonNull - @Override - public abstract String getShortDescription(); - - /** - * Returns a long description for an {@link IDescription}. - * Can be empty but not null. - */ - @NonNull - @Override - public String getLongDescription() { - StringBuilder sb = new StringBuilder(); - - String s = getDescription(); - if (s != null) { - sb.append(s); - } - if (sb.length() > 0) { - sb.append("\n"); - } - - sb.append(String.format("Revision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : "")); - - s = getDescUrl(); - if (s != null && !s.isEmpty()) { - sb.append(String.format("\n\nMore information at %1$s", s)); - } - - s = getReleaseNote(); - if (s != null && !s.isEmpty()) { - sb.append("\n\nRelease note:\n").append(s); - } - - s = getReleaseNoteUrl(); - if (s != null && !s.isEmpty()) { - sb.append("\nRelease note URL: ").append(s); - } - - return sb.toString(); - } - - /** - * A package is local (that is 'installed locally') if it contains a single - * archive that is local. If not local, it's a remote package, only available - * on a remote source for download and installation. - */ - public boolean isLocal() { - return mArchives.length == 1 && mArchives[0].isLocal(); - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * Some types of packages install in a fix location, for example docs and tools. - * In this case the returned folder may already exist with a different archive installed - * at the desired location.
- * For other packages types, such as add-on or platform, the folder name is only partially - * relevant to determine the content and thus a real check will be done to provide an - * existing or new folder depending on the current content of the SDK. - *

- * Note that the installer *will* create all directories returned here just before - * installation so this method must not attempt to create them. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @NonNull - public abstract File getInstallFolder(String osSdkRoot, SdkManager sdkManager); - - /** - * Hook called right before an archive is installed. The archive has already - * been downloaded successfully and will be installed in the directory specified by - * installFolder when this call returns. - *

- * The hook lets the package decide if installation of this specific archive should - * be continue. The installer will still install the remaining packages if possible. - *

- * The base implementation always return true. - *

- * Note that the installer *will* create all directories specified by - * {@link #getInstallFolder} just before installation, so they must not be - * created here. This is also called before the previous install dir is removed - * so the previous content is still there during upgrade. - * - * @param archive The archive that will be installed - * @param monitor The {@link ITaskMonitor} to display errors. - * @param osSdkRoot The OS path of the SDK root folder. - * @param installFolder The folder where the archive will be installed. Note that this - * is not the folder where the archive was temporary - * unzipped. The installFolder, if it exists, contains the old - * archive that will soon be replaced by the new one. - * @return True if installing this archive shall continue, false if it should be skipped. - */ - public boolean preInstallHook(Archive archive, ITaskMonitor monitor, - String osSdkRoot, File installFolder) { - // Nothing to do in base class. - return true; - } - - /** - * Hook called right after a file has been unzipped (during an install). - *

- * The base class implementation makes sure to properly adjust set executable - * permission on Linux and MacOS system if the zip entry was marked as +x. - * - * @param archive The archive that is being installed. - * @param monitor The {@link ITaskMonitor} to display errors. - * @param fileOp The {@link IFileOp} used by the archive installer. - * @param unzippedFile The file that has just been unzipped in the install temp directory. - * @param zipEntry The {@link ZipArchiveEntry} that has just been unzipped. - */ - public void postUnzipFileHook( - Archive archive, - ITaskMonitor monitor, - IFileOp fileOp, - File unzippedFile, - ZipArchiveEntry zipEntry) { - - // if needed set the permissions. - if (sUsingUnixPerm && fileOp.isFile(unzippedFile)) { - // get the mode and test if it contains the executable bit - int mode = zipEntry.getUnixMode(); - if ((mode & 0111) != 0) { - try { - fileOp.setExecutablePermission(unzippedFile); - } catch (IOException ignore) {} - } - } - - } - - /** - * Hook called right after an archive has been installed. - * - * @param archive The archive that has been installed. - * @param monitor The {@link ITaskMonitor} to display errors. - * @param installFolder The folder where the archive was successfully installed. - * Null if the installation failed, in case the archive needs to - * do some cleanup after preInstallHook. - */ - public void postInstallHook(Archive archive, ITaskMonitor monitor, File installFolder) { - // Nothing to do in base class. - } - - /** - * Returns whether the give package represents the same item as the current package. - *

- * Two packages are considered the same if they represent the same thing, except for the - * revision number. - * @param pkg the package to compare. - * @return true if the item as equivalent. - */ - public abstract boolean sameItemAs(Package pkg); - - /** - * Computes whether the given package is a suitable update for the current package. - *

- * An update is just that: a new package that supersedes the current one. If the new - * package does not represent the same item or if it has the same or lower revision as the - * current one, it's not an update. - * - * @param replacementPackage The potential replacement package. - * @return One of the {@link UpdateInfo} values. - * - * @see #sameItemAs(Package) - */ - @NonNull - public abstract UpdateInfo canBeUpdatedBy(Package replacementPackage); - - /** - * Returns an ordering suitable for display like this:
- * - Tools
- * - Platform-Tools
- * - Built-Tools
- * - Docs.
- * - Platform n preview
- * - Platform n
- * - Platform n-1
- * - Samples packages
- * - Add-on based on n preview
- * - Add-on based on n
- * - Add-on based on n-1
- * - Extra packages
- *

- * Important: this must NOT be used to compare if two packages are the same thing. - * This is achieved by {@link #sameItemAs(Package)} or {@link #canBeUpdatedBy(Package)}. - *

- * The order done here is suitable for display, and this may not be the appropriate - * order when comparing whether packages are equal or of greater revision -- if you need - * to compare revisions, then use {@link #getRevision()}{@code .compareTo(rev)} directly. - *

- * This {@link #compareTo(Package)} method is purely an implementation detail to - * perform the right ordering of the packages in the list of available or installed packages. - *

- * Important: Derived classes should consider overriding {@link #comparisonKey()} - * instead of this method. - */ - @Override - public int compareTo(Package other) { - String s1 = this.comparisonKey(); - String s2 = other.comparisonKey(); - - int r = s1.compareTo(s2); - return r; - } - - /** - * Computes a comparison key for each package used by {@link #compareTo(Package)}. - * The key is a string. - * The base package class return a string that encodes the package type, - * the revision number and the platform version, if applicable, in the form: - *

-     *      t:N|v:NNNN.P|r:NNNN|
-     * 
- * All fields must start by a "letter colon" prefix and end with a vertical pipe (|, ASCII 124). - *

- * The string format may change between releases and clients should not - * store them outside of the session or expect them to be consistent between - * different releases. They are purely an internal implementation details of the - * {@link #compareTo(Package)} method. - *

- * Derived classes should get the string from the super class and then append - * or insert their own |-separated content. - * For example an extra vendor name & path can be inserted before the revision - * number, since it has more sorting weight. - */ - @NonNull - protected String comparisonKey() { - - StringBuilder sb = new StringBuilder(); - - sb.append("t:"); //$NON-NLS-1$ - if (this instanceof ToolPackage) { - sb.append(0); - } else if (this instanceof PlatformToolPackage) { - sb.append(1); - } else if (this instanceof BuildToolPackage) { - sb.append(2); - } else if (this instanceof DocPackage) { - sb.append(3); - } else if (this instanceof PlatformPackage) { - sb.append(4); - } else if (this instanceof SamplePackage) { - sb.append(5); - } else if ((this instanceof SystemImagePackage) && ((SystemImagePackage) this).isPlatform()) { - sb.append(6); - } else if (this instanceof AddonPackage) { - sb.append(7); - } else if (this instanceof SystemImagePackage) { - sb.append(8); - } else { - // extras and everything else - sb.append(9); - } - - - // We insert the package version here because it is more important - // than the revision number. - // In the list display, we want package version to be sorted - // top-down, so we'll use 10k-api as the sorting key. The day we - // reach 10k APIs, we'll need to revisit this. - sb.append("|v:"); //$NON-NLS-1$ - if (this instanceof IAndroidVersionProvider) { - AndroidVersion v = ((IAndroidVersionProvider) this).getAndroidVersion(); - - sb.append(String.format("%1$04d.%2$d", //$NON-NLS-1$ - 10000 - v.getApiLevel(), - v.isPreview() ? 1 : 0 - )); - } - - // Append revision number - // Note: pad revision numbers to 4 digits (e.g. make sure 12>3 by comparing 0012 and 0003) - sb.append("|r:"); //$NON-NLS-1$ - FullRevision rev = getRevision(); - sb.append(String.format("%1$04d.%2$04d.%3$04d.", //$NON-NLS-1$ - rev.getMajor(), - rev.getMinor(), - rev.getMicro())); - // Hack: When comparing packages for installation purposes, we want to treat - // "final releases" packages as more important than rc/preview packages. - // However like for the API level above, when sorting for list display purposes - // we want the final release package listed before its rc/preview packages. - if (rev.isPreview()) { - sb.append(rev.getPreview()); - } else { - sb.append('0'); // 0=Final (!preview), to make "18.0" < "18.1" (18 Final < 18 RC1) - } - - sb.append('|'); - return sb.toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Arrays.hashCode(mArchives); - result = prime * result + ((mObsolete == null) ? 0 : mObsolete.hashCode()); - result = prime * result + getRevision().hashCode(); - result = prime * result + ((mSource == null) ? 0 : mSource.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof Package)) { - return false; - } - Package other = (Package) obj; - if (!Arrays.equals(mArchives, other.mArchives)) { - return false; - } - if (mObsolete == null) { - if (other.mObsolete != null) { - return false; - } - } else if (!mObsolete.equals(other.mObsolete)) { - return false; - } - if (!getRevision().equals(other.getRevision())) { - return false; - } - if (mSource == null) { - if (other.mSource != null) { - return false; - } - } else if (!mSource.equals(other.mSource)) { - return false; - } - return true; - } - - // TODO(jbakermalone): This is moved here from the more logical location in PkgDesc.Builder since Package will soon be forked into - // studio and this version deprecated, whereas PkgDesc will not. - protected PkgDesc.Builder setDescriptions(PkgDesc.Builder builder) { - builder.setDescriptionShort(getShortDescription()); - builder.setDescriptionUrl(getDescUrl()); - builder.setListDisplay(getListDisplay()); - builder.setIsObsolete(isObsolete()); - builder.setLicense(getLicense()); - return builder; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PackageParserUtils.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PackageParserUtils.java deleted file mode 100644 index eeee4a9e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PackageParserUtils.java +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.archives.ArchFilter; -import com.android.sdklib.internal.repository.archives.BitSize; -import com.android.sdklib.internal.repository.archives.HostOs; -import com.android.sdklib.internal.repository.archives.LegacyArch; -import com.android.sdklib.internal.repository.archives.LegacyOs; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Node; - -import java.util.Properties; - -/** - * Misc utilities to help extracting elements and attributes out of a repository XML document. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class PackageParserUtils { - - /** - * Parse the {@link ArchFilter} of an <archive> element.. - *

- * Starting with repo schema 10, add-on schema 7 and sys-img schema 3, this is done using - * specific optional elements contained within the <archive> element. - *

- * If none of the new element are defined, for backward compatibility we try to find - * the previous style XML attributes "os" and "arch" in the <archive> element. - * - * @param archiveNode - * @return A new {@link ArchFilter} - */ - @NonNull - public static ArchFilter parseArchFilter(@NonNull Node archiveNode) { - String hos = PackageParserUtils.getOptionalXmlString(archiveNode, SdkRepoConstants.NODE_HOST_OS); - String hb = PackageParserUtils.getOptionalXmlString(archiveNode, SdkRepoConstants.NODE_HOST_BITS); - String jb = PackageParserUtils.getOptionalXmlString(archiveNode, SdkRepoConstants.NODE_JVM_BITS); - String mjv = PackageParserUtils.getOptionalXmlString(archiveNode, SdkRepoConstants.NODE_MIN_JVM_VERSION); - - if (hos != null || hb != null || jb != null || mjv != null) { - NoPreviewRevision rev = null; - try { - rev = NoPreviewRevision.parseRevision(mjv); - } catch (NumberFormatException ignore) {} - - return new ArchFilter( - HostOs.fromXmlName(hos), - BitSize.fromXmlName(hb), - BitSize.fromXmlName(jb), - rev); - } - - Properties props = new Properties(); - - LegacyOs o = (LegacyOs) PackageParserUtils.getEnumAttribute( - archiveNode, SdkRepoConstants.LEGACY_ATTR_OS, LegacyOs.values(), null); - if (o != null) { - props.setProperty(ArchFilter.LEGACY_PROP_OS, o.toString()); - } - - LegacyArch a = (LegacyArch) PackageParserUtils.getEnumAttribute( - archiveNode, SdkRepoConstants.LEGACY_ATTR_ARCH, LegacyArch.values(), null); - if (a != null) { - props.setProperty(ArchFilter.LEGACY_PROP_ARCH, a.toString()); - } - - return new ArchFilter(props); - } - - /** - * Parses a full revision element such as or . - * This supports both the single-integer format as well as the full revision - * format with major/minor/micro/preview sub-elements. - * - * @param revisionNode The node to parse. - * @return A new {@link FullRevision}. If parsing failed, major is set to - * {@link FullRevision#MISSING_MAJOR_REV}. - */ - public static FullRevision parseFullRevisionElement(Node revisionNode) { - // This needs to support two modes: - // - For repository XSD >= 7, contains sub-elements such as or . - // - Otherwise for repository XSD < 7, contains an integer. - // The element is mandatory, so it's easy to distinguish between both cases. - int major = FullRevision.MISSING_MAJOR_REV, - minor = FullRevision.IMPLICIT_MINOR_REV, - micro = FullRevision.IMPLICIT_MICRO_REV, - preview = FullRevision.NOT_A_PREVIEW; - - if (revisionNode != null) { - if (PackageParserUtils.findChildElement(revisionNode, - SdkRepoConstants.NODE_MAJOR_REV) != null) { - // has a sub-element, so it's a repository XSD >= 7. - major = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MAJOR_REV, FullRevision.MISSING_MAJOR_REV); - minor = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MINOR_REV, FullRevision.IMPLICIT_MINOR_REV); - micro = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MICRO_REV, FullRevision.IMPLICIT_MICRO_REV); - preview = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_PREVIEW, FullRevision.NOT_A_PREVIEW); - } else { - try { - String majorStr = revisionNode.getTextContent().trim(); - major = Integer.parseInt(majorStr); - } catch (Exception e) { - } - } - } - - return new FullRevision(major, minor, micro, preview); - } - - /** - * Parses a no-preview revision element such as >. - * This supports both the single-integer format as well as the full revision - * format with major/minor/micro sub-elements. - * - * @param revisionNode The node to parse. - * @return A new {@link NoPreviewRevision}. If parsing failed, major is set to - * {@link FullRevision#MISSING_MAJOR_REV}. - */ - public static NoPreviewRevision parseNoPreviewRevisionElement(Node revisionNode) { - // This needs to support two modes: - // - For addon XSD >= 6, contains sub-elements such as or . - // - Otherwise for addon XSD < 6, contains an integer. - // The element is mandatory, so it's easy to distinguish between both cases. - int major = FullRevision.MISSING_MAJOR_REV, - minor = FullRevision.IMPLICIT_MINOR_REV, - micro = FullRevision.IMPLICIT_MICRO_REV; - - if (revisionNode != null) { - if (PackageParserUtils.findChildElement(revisionNode, - SdkRepoConstants.NODE_MAJOR_REV) != null) { - // has a sub-element, so it's a repository XSD >= 7. - major = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MAJOR_REV, FullRevision.MISSING_MAJOR_REV); - minor = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MINOR_REV, FullRevision.IMPLICIT_MINOR_REV); - micro = PackageParserUtils.getXmlInt(revisionNode, - SdkRepoConstants.NODE_MICRO_REV, FullRevision.IMPLICIT_MICRO_REV); - } else { - try { - String majorStr = revisionNode.getTextContent().trim(); - major = Integer.parseInt(majorStr); - } catch (Exception e) { - } - } - } - - return new NoPreviewRevision(major, minor, micro); - } - - /** - * Returns the first child element with the given XML local name and the same NS URI. - * If xmlLocalName is null, returns the very first child element. - */ - public static Node findChildElement(Node node, String xmlLocalName) { - if (node != null) { - String nsUri = node.getNamespaceURI(); - for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - String nsUriChild = child.getNamespaceURI(); - if ((nsUri == null && nsUriChild == null) || - (nsUri != null && nsUri.equals(nsUriChild))) { - if (xmlLocalName == null || xmlLocalName.equals(child.getLocalName())) { - return child; - } - } - } - } - } - return null; - } - - /** - * Retrieves the value of that XML element as a string. - * Returns an empty string whether the element is missing or empty, - * so you can't tell the difference. - *

- * Note: use {@link #getOptionalXmlString(Node, String)} if you need to know when the - * element is missing versus empty. - * - * @param node The XML parent node to parse. - * @param xmlLocalName The XML local name to find in the parent node. - * @return The text content of the element. Returns an empty string whether the element - * is missing or empty, so you can't tell the difference. - */ - public static String getXmlString(Node node, String xmlLocalName) { - return getXmlString(node, xmlLocalName, ""); //$NON-NLS-1$ - } - - /** - * Retrieves the value of that XML element as a string. - * Returns the defaultValue if the element is missing or empty. - *

- * Note: use {@link #getOptionalXmlString(Node, String)} if you need to know when the - * element is missing versus empty. - * - * @param node The XML parent node to parse. - * @param xmlLocalName The XML local name to find in the parent node. - * @param defaultValue A default value to return if the element is missing. - * @return The text content of the element - * or the defaultValue if the element is missing or empty. - */ - public static String getXmlString(Node node, String xmlLocalName, String defaultValue) { - Node child = findChildElement(node, xmlLocalName); - String content = child == null ? null : child.getTextContent(); - return content == null || content.isEmpty() ? defaultValue : content; - } - - /** - * Retrieves the value of that XML element as a string. - * Returns null when the element is missing, so you can tell between a missing element - * and an empty one. - *

- * Note: use {@link #getXmlString(Node, String)} if you don't need to know when the - * element is missing versus empty. - * - * @param node The XML parent node to parse. - * @param xmlLocalName The XML local name to find in the parent node. - * @return The text content of the element. Returns null when the element is missing. - * Returns an empty string whether the element is present but empty. - */ - public static String getOptionalXmlString(Node node, String xmlLocalName) { - Node child = findChildElement(node, xmlLocalName); - return child == null ? null : child.getTextContent(); //$NON-NLS-1$ - } - - /** - * Retrieves the value of that XML element as an integer. - * Returns the default value when the element is missing or is not an integer. - */ - public static int getXmlInt(Node node, String xmlLocalName, int defaultValue) { - String s = getXmlString(node, xmlLocalName); - try { - return Integer.parseInt(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * Retrieves the value of that XML element as a long. - * Returns the default value when the element is missing or is not an integer. - */ - public static long getXmlLong(Node node, String xmlLocalName, long defaultValue) { - String s = getXmlString(node, xmlLocalName); - try { - return Long.parseLong(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * Retrieve an attribute which value must match one of the given enums using a - * case-insensitive name match. - * - * Returns defaultValue if the attribute does not exist or its value does not match - * the given enum values. - */ - public static Object getEnumAttribute( - Node archiveNode, - String attrName, - Object[] values, - Object defaultValue) { - - Node attr = archiveNode.getAttributes().getNamedItem(attrName); - if (attr != null) { - String found = attr.getNodeValue(); - for (Object value : values) { - if (value.toString().equalsIgnoreCase(found)) { - return value; - } - } - } - - return defaultValue; - } - - /** - * Utility method that returns a property from a {@link Properties} object. - * Returns the default value if props is null or if the property is not defined. - * - * @param props The {@link Properties} to search into. - * If null, the default value is returned. - * @param propKey The name of the property. Must not be null. - * @param defaultValue The default value to return if {@code props} is null or if the - * key is not found. Can be null. - * @return The string value of the given key in the properties, or null if the key - * isn't found or if {@code props} is null. - */ - @Nullable - public static String getProperty( - @Nullable Properties props, - @NonNull String propKey, - @Nullable String defaultValue) { - if (props == null) { - return defaultValue; - } - return props.getProperty(propKey, defaultValue); - } - - /** - * Utility method that returns an integer property from a {@link Properties} object. - * Returns the default value if props is null or if the property is not defined or - * cannot be parsed to an integer. - * - * @param props The {@link Properties} to search into. - * If null, the default value is returned. - * @param propKey The name of the property. Must not be null. - * @param defaultValue The default value to return if {@code props} is null or if the - * key is not found. Can be null. - * @return The integer value of the given key in the properties, or the {@code defaultValue}. - */ - public static int getPropertyInt( - @Nullable Properties props, - @NonNull String propKey, - int defaultValue) { - String s = props != null ? props.getProperty(propKey, null) : null; - if (s != null) { - try { - return Integer.parseInt(s); - } catch (Exception ignore) {} - } - return defaultValue; - } - - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a full - * revision (major.minor.micro.preview). - * - * @param props The properties to parse. - * @return A {@link FullRevision} or null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static FullRevision getPropertyFull( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - FullRevision rev = null; - if (revStr != null) { - try { - rev = FullRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a major - * revision (major integer, no minor/micro/preview parts.) - * - * @param props The properties to parse. - * @return A {@link MajorRevision} or null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static MajorRevision getPropertyMajor( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - MajorRevision rev = null; - if (revStr != null) { - try { - rev = MajorRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a no-preview - * revision (major.minor.micro integers but no preview part.) - * - * @param props The properties to parse. - * @return A {@link NoPreviewRevision} or - * null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static NoPreviewRevision getPropertyNoPreview( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - NoPreviewRevision rev = null; - if (revStr != null) { - try { - rev = NoPreviewRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformPackage.java deleted file mode 100644 index ff4e4bb7..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformPackage.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.utils.Pair; - -import org.w3c.dom.Node; - -import java.io.File; -import java.util.Map; -import java.util.Properties; - -/** - * Represents a platform XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class PlatformPackage extends MinToolsPackage - implements IAndroidVersionProvider, ILayoutlibVersion { - - /** The package version, for platform, add-on and doc packages. */ - private final AndroidVersion mVersion; - - /** The version, a string, for platform packages. */ - private final String mVersionName; - - /** The ABI of the system-image included in this platform. Can be null but not empty. */ - private final String mIncludedAbi; - - /** The helper handling the layoutlib version. */ - private final LayoutlibVersionMixin mLayoutlibVersion; - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new platform package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public PlatformPackage( - SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mVersionName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_VERSION); - - int apiLevel = - PackageParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0); - String codeName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME); - if (codeName.isEmpty()) { - codeName = null; - } - mVersion = new AndroidVersion(apiLevel, codeName); - - mIncludedAbi = PackageParserUtils.getOptionalXmlString(packageNode, - SdkRepoConstants.NODE_ABI_INCLUDED); - - mLayoutlibVersion = new LayoutlibVersionMixin(packageNode); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newPlatform(mVersion, (MajorRevision) getRevision(), getMinToolsRevision())) - .create(); - } - - /** - * Creates a new platform package based on an actual {@link IAndroidTarget} (which - * must have {@link IAndroidTarget#isPlatform()} true) from the {@link SdkManager}. - * This is used to list local SDK folders in which case there is one archive which - * URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create(@NonNull IAndroidTarget target, @Nullable Properties props) { - return new PlatformPackage(target, props); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected PlatformPackage(@NonNull IAndroidTarget target, @Nullable Properties props) { - this(null /*source*/, target, props); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected PlatformPackage(@Nullable SdkSource source, - @NonNull IAndroidTarget target, - @Nullable Properties props) { - super( source, //source - props, //properties - target.getRevision(), //revision - null, //license - target.getDescription(), //description - null, //descUrl - target.getLocation() //archiveOsPath - ); - - mVersion = target.getVersion(); - mVersionName = target.getVersionName(); - mLayoutlibVersion = new LayoutlibVersionMixin(props); - mIncludedAbi = props == null ? null : props.getProperty(PkgProps.PLATFORM_INCLUDED_ABI); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newPlatform(mVersion, (MajorRevision) getRevision(), getMinToolsRevision())) - .create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - mVersion.saveProperties(props); - mLayoutlibVersion.saveProperties(props); - - if (mVersionName != null) { - props.setProperty(PkgProps.PLATFORM_VERSION, mVersionName); - } - - if (mIncludedAbi != null) { - props.setProperty(PkgProps.PLATFORM_INCLUDED_ABI, mIncludedAbi); - } - - } - - /** Returns the version, a string, for platform packages. */ - public String getVersionName() { - return mVersionName; - } - - /** Returns the package version, for platform, add-on and doc packages. */ - @Override @NonNull - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** - * Returns the ABI of the system-image included in this platform. - * - * @return Null if the platform does not include any system-image. - * Otherwise should be a valid non-empty ABI string (e.g. "x86" or "armeabi-v7a"). - */ - public String getIncludedAbi() { - return mIncludedAbi; - } - - /** - * Returns the layoutlib version. Mandatory starting with repository XSD rev 4. - *

- * The first integer is the API of layoublib, which should be > 0. - * It will be equal to {@link ILayoutlibVersion#LAYOUTLIB_API_NOT_SPECIFIED} (0) - * if the layoutlib version isn't specified. - *

- * The second integer is the revision for that given API. It is >= 0 - * and works as a minor revision number, incremented for the same API level. - * - * @since sdk-repository-4.xsd - */ - @Override - public Pair getLayoutlibVersion() { - return mLayoutlibVersion.getLayoutlibVersion(); - } - - /** - * Returns a string identifier to install this package from the command line. - * For platforms, we use "android-N" where N is the API or the preview codename. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return AndroidTargetHash.getPlatformHashString(mVersion); - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - String s; - if (mVersion.isPreview()) { - s = String.format("SDK Platform Android %1$s Preview%2$s", - getVersionName(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - } else { - s = String.format("SDK Platform Android %1$s%2$s", - getVersionName(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - } - - return s; - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - String s; - if (mVersion.isPreview()) { - s = String.format("SDK Platform Android %1$s Preview, revision %2$s%3$s", - getVersionName(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - } else { - s = String.format("SDK Platform Android %1$s, API %2$d, revision %3$s%4$s", - getVersionName(), - mVersion.getApiLevel(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$ - } - - return s; - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A platform package is typically installed in SDK/platforms/android-"version". - * However if we can find a different directory under SDK/platform that already - * has this platform version installed, we'll use that one. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - - // First find if this platform is already installed. If so, reuse the same directory. - for (IAndroidTarget target : sdkManager.getTargets()) { - if (target.isPlatform() && target.getVersion().equals(mVersion)) { - return new File(target.getLocation()); - } - } - - File platforms = new File(osSdkRoot, SdkConstants.FD_PLATFORMS); - File folder = new File(platforms, - String.format("android-%s", getAndroidVersion().getApiString())); //$NON-NLS-1$ - - return folder; - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof PlatformPackage) { - PlatformPackage newPkg = (PlatformPackage)pkg; - - // check they are the same version. - return newPkg.getAndroidVersion().equals(this.getAndroidVersion()); - } - - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + - ((mLayoutlibVersion == null) ? 0 : mLayoutlibVersion.hashCode()); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - result = prime * result + ((mVersionName == null) ? 0 : mVersionName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof PlatformPackage)) { - return false; - } - PlatformPackage other = (PlatformPackage) obj; - if (mLayoutlibVersion == null) { - if (other.mLayoutlibVersion != null) { - return false; - } - } else if (!mLayoutlibVersion.equals(other.mLayoutlibVersion)) { - return false; - } - if (mVersion == null) { - if (other.mVersion != null) { - return false; - } - } else if (!mVersion.equals(other.mVersion)) { - return false; - } - if (mVersionName == null) { - if (other.mVersionName != null) { - return false; - } - } else if (!mVersionName.equals(other.mVersionName)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformToolPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformToolPackage.java deleted file mode 100644 index 85c69532..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/PlatformToolPackage.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.AdbWrapper; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; -import org.w3c.dom.Node; - -import java.io.File; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - * Represents a platform-tool XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class PlatformToolPackage extends FullRevisionPackage { - - /** The value returned by {@link PlatformToolPackage#installId()}. */ - public static final String INSTALL_ID = "platform-tools"; //$NON-NLS-1$ - /** The value returned by {@link PlatformToolPackage#installId()}. */ - public static final String INSTALL_ID_PREVIEW = "platform-tools-preview"; //$NON-NLS-1$ - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new platform-tool package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public PlatformToolPackage(SdkSource source, Node packageNode, - String nsUri, Map licenses) { - super(source, packageNode, nsUri, licenses); - - mPkgDesc = setDescriptions(PkgDesc.Builder.newPlatformTool(getRevision())).create(); - } - - /** - * Manually create a new package with one archive and the given attributes or properties. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - - PlatformToolPackage ptp = new PlatformToolPackage(source, props, revision, license, - description, descUrl, archiveOsPath); - - File platformToolsFolder = new File(archiveOsPath); - String error = null; - if (!platformToolsFolder.isDirectory()) { - error = "platform-tools folder is missing"; - } else { - File[] files = platformToolsFolder.listFiles(); - if (files == null || files.length == 0) { - error = "platform-tools folder is empty"; - } else { - Set names = new HashSet(); - for (File file : files) { - names.add(file.getName()); - } - - // Package-tools revision 17+ matches sdk-repository-8 and above - // and only requires adb (other tools moved to the build-tool packages.) - String[] expected = new String[] { SdkConstants.FN_ADB }; - if (ptp.getRevision().getMajor() < 17) { - // Platform-tools before revision 17 should have adb, aapt, aidl and dx. - expected = new String[] { SdkConstants.FN_ADB, - SdkConstants.FN_AAPT, - SdkConstants.FN_AIDL, - SdkConstants.FN_DX }; - } - - for (String name : expected) { - if (!names.contains(name)) { - if (error == null) { - error = "platform-tools folder is missing "; - } else { - error += ", "; - } - error += name; - } - } - } - } - - if (error != null) { - String shortDesc = ptp.getShortDescription() + " [*]"; //$NON-NLS-1$ - - String longDesc = String.format( - "Broken Platform-Tools Package: %1$s\n" + - "[*] Package cannot be used due to error: %2$s", - description, - error); - - BrokenPackage ba = new BrokenPackage(props, shortDesc, longDesc, - IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, - IExactApiLevelDependency.API_LEVEL_INVALID, - archiveOsPath, - PkgDesc.Builder.newPlatformTool(ptp.getRevision()) - .setDescriptionShort(shortDesc) - .create()); - return ba; - } - - - return ptp; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected PlatformToolPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - - mPkgDesc = setDescriptions(PkgDesc.Builder.newPlatformTool(getRevision())).create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Returns a string identifier to install this package from the command line. - * For platform-tools, we use "platform-tools" or "platform-tools-preview" since - * this package type is unique. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - if (getRevision().isPreview()) { - return INSTALL_ID_PREVIEW; - } else { - return INSTALL_ID; - } - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("Android SDK Platform-tools%1$s", - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("Android SDK Platform-tools, revision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** Returns a long description for an {@link IDescription}. */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A "platform-tool" package should always be located in SDK/platform-tools. - * There can be only one installed at once. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - return new File(osSdkRoot, SdkConstants.FD_PLATFORM_TOOLS); - } - - /** - * Check whether 2 platform-tool packages are the same and have the - * same preview bit. - */ - @Override - public boolean sameItemAs(Package pkg) { - return sameItemAs(pkg, PreviewComparison.COMPARE_TYPE); - } - - @Override - public boolean sameItemAs(Package pkg, PreviewComparison comparePreview) { - // only one platform-tool package so any platform-tool package is the same item. - if (pkg instanceof PlatformToolPackage) { - switch (comparePreview) { - case IGNORE: - return true; - - case COMPARE_NUMBER: - // Voluntary break-through. - case COMPARE_TYPE: - // There's only one platform-tools so the preview number doesn't matter; - // however previews can only match previews by default so both cases - // are treated the same. - return pkg.getRevision().isPreview() == getRevision().isPreview(); - } - } - return false; - } - - /** - * Hook called right before an archive is installed. - * This is used here to stop ADB before trying to replace the platform-tool package. - * - * @param archive The archive that will be installed - * @param monitor The {@link ITaskMonitor} to display errors. - * @param osSdkRoot The OS path of the SDK root folder. - * @param installFolder The folder where the archive will be installed. Note that this - * is not the folder where the archive was temporary - * unzipped. The installFolder, if it exists, contains the old - * archive that will soon be replaced by the new one. - * @return True if installing this archive shall continue, false if it should be skipped. - */ - @Override - public boolean preInstallHook(Archive archive, ITaskMonitor monitor, - String osSdkRoot, File installFolder) { - AdbWrapper aw = new AdbWrapper(osSdkRoot, monitor); - aw.stopAdb(); - return super.preInstallHook(archive, monitor, osSdkRoot, installFolder); - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SamplePackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SamplePackage.java deleted file mode 100644 index d31805ed..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SamplePackage.java +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.AndroidVersion.AndroidVersionException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.w3c.dom.Node; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Map; -import java.util.Properties; - -/** - * Represents a sample XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SamplePackage extends MinToolsPackage - implements IAndroidVersionProvider, IMinApiLevelDependency { - - /** The matching platform version. */ - private final AndroidVersion mVersion; - - /** - * The minimal API level required by this extra package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - private final int mMinApiLevel; - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new sample package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public SamplePackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - int apiLevel = - PackageParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0); - String codeName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME); - if (codeName.isEmpty()) { - codeName = null; - } - mVersion = new AndroidVersion(apiLevel, codeName); - - mMinApiLevel = PackageParserUtils.getXmlInt(packageNode, - SdkRepoConstants.NODE_MIN_API_LEVEL, - MIN_API_LEVEL_NOT_SPECIFIED); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newSample(mVersion, (MajorRevision) getRevision(), getMinToolsRevision())) - .create(); - } - - /** - * Creates a new sample package based on an actual {@link IAndroidTarget} (which - * must have {@link IAndroidTarget#isPlatform()} true) from the {@link SdkManager}. - *

- * The target must have an existing sample directory that uses the /samples - * root form rather than the old form where the samples dir was located under the - * platform dir. - *

- * This is used to list local SDK folders in which case there is one archive which - * URL is the actual samples path location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create(IAndroidTarget target, Properties props) { - return new SamplePackage(target, props); - } - - private SamplePackage(IAndroidTarget target, Properties props) { - super( null, //source - props, //properties - 0, //revision will be taken from props - null, //license - null, //description - null, //descUrl - target.getPath(IAndroidTarget.SAMPLES) //archiveOsPath - ); - - mVersion = target.getVersion(); - - mMinApiLevel = getPropertyInt(props, PkgProps.SAMPLE_MIN_API_LEVEL, - MIN_API_LEVEL_NOT_SPECIFIED); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newSample(mVersion, (MajorRevision) getRevision(), getMinToolsRevision())) - .create(); - } - - /** - * Creates a new sample package from an actual directory path and previously - * saved properties. - *

- * This is used to list local SDK folders in which case there is one archive which - * URL is the actual samples path location. - *

- * By design, this creates a package with one and only one archive. - * - * @throws AndroidVersionException if the {@link AndroidVersion} can't be restored - * from properties. - */ - public static Package create(String archiveOsPath, Properties props) - throws AndroidVersionException { - return new SamplePackage(archiveOsPath, props); - } - - private SamplePackage(String archiveOsPath, Properties props) throws AndroidVersionException { - super(null, //source - props, //properties - 0, //revision will be taken from props - null, //license - null, //description - null, //descUrl - archiveOsPath //archiveOsPath - ); - - mVersion = new AndroidVersion(props); - - mMinApiLevel = getPropertyInt(props, PkgProps.SAMPLE_MIN_API_LEVEL, - MIN_API_LEVEL_NOT_SPECIFIED); - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newSample(mVersion, (MajorRevision) getRevision(), getMinToolsRevision())) - .create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - mVersion.saveProperties(props); - - if (getMinApiLevel() != MIN_API_LEVEL_NOT_SPECIFIED) { - props.setProperty(PkgProps.SAMPLE_MIN_API_LEVEL, Integer.toString(getMinApiLevel())); - } - } - - /** - * Returns the minimal API level required by this extra package, if > 0, - * or {@link #MIN_API_LEVEL_NOT_SPECIFIED} if there is no such requirement. - */ - @Override - public int getMinApiLevel() { - return mMinApiLevel; - } - - /** Returns the matching platform version. */ - @Override @NonNull - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** - * Returns a string identifier to install this package from the command line. - * For samples, we use "sample-N" where N is the API or the preview codename. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return "sample-" + mVersion.getApiString(); //$NON-NLS-1$ - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - String s = String.format("Samples for SDK API %1$s%2$s%3$s", - mVersion.getApiString(), - mVersion.isPreview() ? " Preview" : "", - isObsolete() ? " (Obsolete)" : ""); - return s; - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - String s = String.format("Samples for SDK API %1$s%2$s, revision %3$s%4$s", - mVersion.getApiString(), - mVersion.isPreview() ? " Preview" : "", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - return s; - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the <description> field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A sample package is typically installed in SDK/samples/android-"version". - * However if we can find a different directory that already has this sample - * version installed, we'll use that one. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - - // The /samples dir at the root of the SDK - File samplesRoot = new File(osSdkRoot, SdkConstants.FD_SAMPLES); - - // First find if this sample is already installed. If so, reuse the same directory. - for (IAndroidTarget target : sdkManager.getTargets()) { - if (target.isPlatform() && - target.getVersion().equals(mVersion)) { - String p = target.getPath(IAndroidTarget.SAMPLES); - File f = new File(p); - if (f.isDirectory()) { - // 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 folder = new File(samplesRoot, - String.format("android-%s", getAndroidVersion().getApiString())); //$NON-NLS-1$ - - for (int n = 1; folder.exists(); n++) { - // Keep trying till we find an unused directory. - folder = new File(samplesRoot, - String.format("android-%s_%d", getAndroidVersion().getApiString(), n)); //$NON-NLS-1$ - } - - return folder; - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof SamplePackage) { - SamplePackage newPkg = (SamplePackage)pkg; - - // check they are the same version. - return newPkg.getAndroidVersion().equals(this.getAndroidVersion()); - } - - return false; - } - - /** - * Makes sure the base /samples folder exists before installing. - * - * {@inheritDoc} - */ - @Override - public boolean preInstallHook(Archive archive, - ITaskMonitor monitor, - String osSdkRoot, - File installFolder) { - - if (installFolder != null && installFolder.isDirectory()) { - // Get the hash computed during the last installation - String storedHash = readContentHash(installFolder); - if (storedHash != null && !storedHash.isEmpty()) { - - // Get the hash of the folder now - String currentHash = computeContentHash(installFolder); - - if (!storedHash.equals(currentHash)) { - // The hashes differ. The content was modified. - // Ask the user if we should still wipe the old samples. - - String pkgName = archive.getParentPackage().getShortDescription(); - - String msg = String.format( - "-= Warning ! =-\n" + - "You are about to replace the content of the folder:\n " + - " %1$s\n" + - "by the new package:\n" + - " %2$s.\n" + - "\n" + - "However it seems that the content of the existing samples " + - "has been modified since it was last installed. Are you sure " + - "you want to DELETE the existing samples? This cannot be undone.\n" + - "Please select YES to delete the existing sample and replace them " + - "by the new ones.\n" + - "Please select NO to skip this package. You can always install it later.", - installFolder.getAbsolutePath(), - pkgName); - - // Returns true if we can wipe & replace. - return monitor.displayPrompt("SDK Manager: overwrite samples?", msg); - } - } - } - - // The default is to allow installation - return super.preInstallHook(archive, monitor, osSdkRoot, installFolder); - } - - /** - * Computes a hash of the installed content (in case of successful install.) - * - * {@inheritDoc} - */ - @Override - public void postInstallHook(Archive archive, ITaskMonitor monitor, File installFolder) { - super.postInstallHook(archive, monitor, installFolder); - - if (installFolder != null) { - String h = computeContentHash(installFolder); - saveContentHash(installFolder, h); - } - } - - /** - * Set all the files from a sample package as read-only so that - * users don't end up modifying sources by mistake in Eclipse - * (samples are copied if using the NPW > Create from sample.) - */ - @Override - public void postUnzipFileHook( - Archive archive, - ITaskMonitor monitor, - IFileOp fileOp, - File unzippedFile, - ZipArchiveEntry zipEntry) { - super.postUnzipFileHook(archive, monitor, fileOp, unzippedFile, zipEntry); - - if (fileOp.isFile(unzippedFile) && - !SdkConstants.FN_SOURCE_PROP.equals(unzippedFile.getName())) { - fileOp.setReadOnly(unzippedFile); - } - } - - /** - * Reads the hash from the properties file, if it exists. - * Returns null if something goes wrong, e.g. there's no property file or - * it doesn't contain our hash. Returns an empty string if the hash wasn't - * correctly computed last time by {@link #saveContentHash(File, String)}. - */ - private String readContentHash(File folder) { - Properties props = new Properties(); - - FileInputStream fis = null; - try { - File f = new File(folder, SdkConstants.FN_CONTENT_HASH_PROP); - if (f.isFile()) { - fis = new FileInputStream(f); - props.load(fis); - return props.getProperty("content-hash", null); //$NON-NLS-1$ - } - } catch (Exception e) { - // ignore - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - } - } - } - - return null; - } - - /** - * Saves the hash using a properties file - */ - private void saveContentHash(File folder, String hash) { - Properties props = new Properties(); - - props.setProperty("content-hash", hash == null ? "" : hash); //$NON-NLS-1$ //$NON-NLS-2$ - - FileOutputStream fos = null; - try { - File f = new File(folder, SdkConstants.FN_CONTENT_HASH_PROP); - fos = new FileOutputStream(f); - props.store( fos, "## Android - hash of this archive."); //$NON-NLS-1$ - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - } - } - } - } - - /** - * Computes a hash of the files names and sizes installed in the folder - * using the SHA-1 digest. - * Returns null if the digest algorithm is not available. - */ - private String computeContentHash(File installFolder) { - MessageDigest md = null; - try { - // SHA-1 is a standard algorithm. - // http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppB - md = MessageDigest.getInstance("SHA-1"); //$NON-NLS-1$ - } catch (NoSuchAlgorithmException e) { - // We're unlikely to get there unless this JVM is not spec conforming - // in which case there won't be any hash available. - } - - if (md != null) { - hashDirectoryContent(installFolder, md); - return getDigestHexString(md); - } - - return null; - } - - /** - * Computes a hash of the *content* of this directory. The hash only uses - * the files names and the file sizes. - */ - private void hashDirectoryContent(File folder, MessageDigest md) { - if (folder == null || md == null || !folder.isDirectory()) { - return; - } - - for (File f : folder.listFiles()) { - if (f.isDirectory()) { - hashDirectoryContent(f, md); - - } else { - String name = f.getName(); - - // Skip the file we use to store the content hash - if (name == null || SdkConstants.FN_CONTENT_HASH_PROP.equals(name)) { - continue; - } - - try { - md.update(name.getBytes(SdkConstants.UTF_8)); - } catch (UnsupportedEncodingException e) { - // There is no valid reason for UTF-8 to be unsupported. Ignore. - } - try { - long len = f.length(); - md.update((byte) (len & 0x0FF)); - md.update((byte) ((len >> 8) & 0x0FF)); - md.update((byte) ((len >> 16) & 0x0FF)); - md.update((byte) ((len >> 24) & 0x0FF)); - - } catch (SecurityException e) { - // Might happen if file is not readable. Ignore. - } - } - } - } - - /** - * Returns a digest as an hex string. - */ - private String getDigestHexString(MessageDigest digester) { - // Create an hex string from the digest - byte[] digest = digester.digest(); - int n = digest.length; - String hex = "0123456789abcdef"; //$NON-NLS-1$ - char[] hexDigest = new char[n * 2]; - for (int i = 0; i < n; i++) { - int b = digest[i] & 0x0FF; - hexDigest[i*2 + 0] = hex.charAt(b >>> 4); - hexDigest[i*2 + 1] = hex.charAt(b & 0x0f); - } - - return new String(hexDigest); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SourcePackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SourcePackage.java deleted file mode 100644 index 6942431e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SourcePackage.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.AndroidVersion.AndroidVersionException; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.w3c.dom.Node; - -import java.io.File; -import java.util.Map; -import java.util.Properties; - -/** - * Represents a source XML node in an SDK repository. - *

- * Note that a source package has a version and thus implements {@link IAndroidVersionProvider}. - * However there is no mandatory dependency that limits installation so this does not - * implement {@link IPlatformDependency}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SourcePackage extends MajorRevisionPackage implements IAndroidVersionProvider { - - /** The package version, for platform, add-on and doc packages. */ - private final AndroidVersion mVersion; - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new source package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public SourcePackage( - SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - int apiLevel = - PackageParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_API_LEVEL, 0); - String codeName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME); - if (codeName.isEmpty()) { - codeName = null; - } - mVersion = new AndroidVersion(apiLevel, codeName); - - mPkgDesc = setDescriptions(PkgDesc.Builder.newSource(mVersion, (MajorRevision)getRevision())).create(); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SourcePackage( - AndroidVersion platformVersion, - int revision, - Properties props, - String localOsPath) { - this(null /*source*/, platformVersion, revision, props, localOsPath); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SourcePackage( - SdkSource source, - AndroidVersion platformVersion, - int revision, - Properties props, - String localOsPath) { - super( source, //source - props, //properties - revision, //revision - null, //license - null, //description - null, //descUrl - localOsPath //archiveOsPath - ); - mVersion = platformVersion; - - mPkgDesc = setDescriptions(PkgDesc.Builder.newSource(mVersion, (MajorRevision) getRevision())).create(); - } - - /** - * Creates either a valid {@link SourcePackage} or a {@link BrokenPackage}. - *

- * If the source directory contains valid properties, this creates a new {@link SourcePackage} - * with the android version listed in the properties. - * Otherwise returns a new {@link BrokenPackage} with some explanation on what failed. - * - * @param srcDir The SDK/sources/android-N folder - * @param props The properties located in {@code srcDir} or null if not found. - * @return A new {@link SourcePackage} or a new {@link BrokenPackage}. - */ - public static Package create(File srcDir, Properties props) { - AndroidVersion version = null; - String error = null; - - // Try to load the android version from the sources.props. - // If we don't find them, it would explain why this package is broken. - if (props == null) { - error = String.format("Missing file %1$s", SdkConstants.FN_SOURCE_PROP); - } else { - try { - version = new AndroidVersion(props); - // The constructor will extract the revision from the properties - // and it will not consider a missing revision as being fatal. - return new SourcePackage(version, 0 /*revision*/, props, srcDir.getAbsolutePath()); - } catch (AndroidVersionException e) { - error = String.format("Invalid file %1$s: %2$s", - SdkConstants.FN_SOURCE_PROP, - e.getMessage()); - } - } - - if (version == null) { - try { - // Try to parse the first number out of the platform folder name. - // This is just a wild guess in case we can create a broken package using that info. - String platform = srcDir.getParentFile().getName(); - platform = platform.replaceAll("[^0-9]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$ - int pos = platform.indexOf(' '); - if (pos >= 0) { - platform = platform.substring(0, pos); - } - int apiLevel = Integer.parseInt(platform); - version = new AndroidVersion(apiLevel, null /*codename*/); - } catch (Exception ignore) { - } - } - - StringBuilder sb = new StringBuilder("Broken Source Package"); - if (version != null) { - sb.append(String.format(", API %1$s", version.getApiString())); - } - - String shortDesc = sb.toString(); - - if (error != null) { - sb.append('\n').append(error); - } - - String longDesc = sb.toString(); - - IPkgDesc desc = PkgDesc.Builder - .newSource(version != null ? version : new AndroidVersion(0, null), - new MajorRevision(MajorRevision.MISSING_MAJOR_REV)) - .setDescriptionShort(shortDesc) - .create(); - - return new BrokenPackage(props, shortDesc, longDesc, - IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, - version==null ? IExactApiLevelDependency.API_LEVEL_INVALID : version.getApiLevel(), - srcDir.getAbsolutePath(), - desc); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - mVersion.saveProperties(props); - } - - /** - * Returns the android version of this package. - */ - @Override @NonNull - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** - * Returns a string identifier to install this package from the command line. - * For sources, we use "source-N" where N is the API or the preview codename. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - return "source-" + mVersion.getApiString(); //$NON-NLS-1$ - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - if (mVersion.isPreview()) { - return String.format("Sources for Android '%1$s' Preview SDK%2$s", - mVersion.getCodename(), - isObsolete() ? " (Obsolete)" : ""); - } else { - return String.format("Sources for Android SDK%2$s", - mVersion.getApiLevel(), - isObsolete() ? " (Obsolete)" : ""); - } - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - if (mVersion.isPreview()) { - return String.format("Sources for Android '%1$s' Preview SDK, revision %2$s%3$s", - mVersion.getCodename(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } else { - return String.format("Sources for Android SDK, API %1$d, revision %2$s%3$s", - mVersion.getApiLevel(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the {@code description} field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A sources package is typically installed in SDK/sources/platform. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - File folder = new File(osSdkRoot, SdkConstants.FD_PKG_SOURCES); - folder = new File(folder, "android-" + mVersion.getApiString()); //$NON-NLS-1$ - return folder; - } - - /** - * Set all the files from a source package as read-only - * so that users don't end up modifying sources by mistake in Eclipse. - */ - @Override - public void postUnzipFileHook( - Archive archive, - ITaskMonitor monitor, - IFileOp fileOp, - File unzippedFile, - ZipArchiveEntry zipEntry) { - super.postUnzipFileHook(archive, monitor, fileOp, unzippedFile, zipEntry); - - if (fileOp.isFile(unzippedFile) && - !SdkConstants.FN_SOURCE_PROP.equals(unzippedFile.getName())) { - fileOp.setReadOnly(unzippedFile); - } - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof SourcePackage) { - SourcePackage newPkg = (SourcePackage)pkg; - - // check they are the same version. - return getAndroidVersion().equals(newPkg.getAndroidVersion()); - } - - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof SourcePackage)) { - return false; - } - SourcePackage other = (SourcePackage) obj; - if (mVersion == null) { - if (other.mVersion != null) { - return false; - } - } else if (!mVersion.equals(other.mVersion)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SystemImagePackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SystemImagePackage.java deleted file mode 100644 index c5ce04a7..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/SystemImagePackage.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.AndroidVersion.AndroidVersionException; -import com.android.sdklib.SdkManager; -import com.android.sdklib.SystemImage; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.*; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.sdklib.repository.local.LocalSysImgPkgInfo; -import org.w3c.dom.Node; - -import java.io.File; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * Represents a system-image XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SystemImagePackage extends MajorRevisionPackage - implements IAndroidVersionProvider, IPlatformDependency { - - /** The package version, for platform, add-on and doc packages. */ - private final AndroidVersion mVersion; - - /** The ABI of the system-image. Must not be null nor empty. */ - private final String mAbi; - - private final IPkgDesc mPkgDesc; - - private final IdDisplay mTag; - private final IdDisplay mAddonVendor; - - /** - * Creates a new system-image package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public SystemImagePackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - int apiLevel = - PackageParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_API_LEVEL, 0); - String codeName = - PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME); - if (codeName.isEmpty()) { - codeName = null; - } - mVersion = new AndroidVersion(apiLevel, codeName); - - mAbi = PackageParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_ABI); - - // tag id - String tagId = PackageParserUtils.getXmlString(packageNode, - SdkSysImgConstants.ATTR_TAG_ID, - SystemImage.DEFAULT_TAG.getId()); - String tagDisp = PackageParserUtils.getOptionalXmlString(packageNode, - SdkSysImgConstants.ATTR_TAG_DISPLAY); - if (tagDisp == null || tagDisp.isEmpty()) { - tagDisp = LocalSysImgPkgInfo.tagIdToDisplay(tagId); - } - assert tagId != null; - assert tagDisp != null; - mTag = new IdDisplay(tagId, tagDisp); - - - Node addonNode = - PackageParserUtils.findChildElement(packageNode, SdkSysImgConstants.NODE_ADD_ON); - - IPkgDesc desc = null; - IdDisplay vendor = null; - - if (addonNode == null) { - // A platform system-image - desc = setDescriptions(PkgDesc.Builder - .newSysImg(mVersion, mTag, mAbi, (MajorRevision) getRevision())) - .create(); - } else { - // An add-on system-image - String vendorId = PackageParserUtils.getXmlString( - addonNode, - SdkAddonConstants.NODE_VENDOR_ID); - String vendorDisp = PackageParserUtils.getXmlString( - addonNode, - SdkAddonConstants.NODE_VENDOR_DISPLAY, - vendorId); - - assert !vendorId.isEmpty(); - assert !vendorDisp.isEmpty(); - - vendor = new IdDisplay(vendorId, vendorDisp); - - desc = setDescriptions(PkgDesc.Builder - .newAddonSysImg(mVersion, vendor, mTag, mAbi, (MajorRevision) getRevision())) - .create(); - } - - mPkgDesc = desc; - mAddonVendor = vendor; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - public SystemImagePackage( - AndroidVersion platformVersion, - int revision, - String abi, - Properties props, - String localOsPath) { - this(null /*source*/, platformVersion, revision, abi, props, localOsPath); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SystemImagePackage( - SdkSource source, - AndroidVersion platformVersion, - int revision, - String abi, - Properties props, - String localOsPath) { - super( source, //source - props, //properties - revision, //revision - null, //license - null, //description - null, //descUrl - localOsPath //archiveOsPath - ); - mVersion = platformVersion; - if (abi == null && props != null) { - abi = props.getProperty(PkgProps.SYS_IMG_ABI); - } - assert abi != null : "To use this SystemImagePackage constructor you must pass an ABI as a parameter or as a PROP_ABI property"; - mAbi = abi; - - mTag = LocalSysImgPkgInfo.extractTagFromProps(props); - - String vendorId = getProperty(props, PkgProps.ADDON_VENDOR_ID, null); - String vendorDisp = getProperty(props, PkgProps.ADDON_VENDOR_DISPLAY, vendorId); - - IPkgDesc desc = null; - IdDisplay vendor = null; - - if (vendorId == null) { - // A platform system-image - desc = setDescriptions(PkgDesc.Builder.newSysImg(mVersion, mTag, mAbi, (MajorRevision)getRevision())).create(); - } - else { - // An add-on system-image - assert !vendorId.isEmpty(); - assert !vendorDisp.isEmpty(); - - vendor = new IdDisplay(vendorId, vendorDisp); - - desc = setDescriptions(PkgDesc.Builder.newAddonSysImg(mVersion, vendor, mTag, mAbi, (MajorRevision)getRevision())).create(); - } - - mPkgDesc = desc; - mAddonVendor = vendor; - } - - /** - * Creates a {@link BrokenPackage} representing a system image that failed to load - * with the regular {@link SdkManager} workflow. - * - * @param abiDir The SDK/system-images/android-N/tag/abi folder - * @param props The properties located in {@code abiDir} or null if not found. - * @return A new {@link BrokenPackage} that represents this installed package. - */ - public static Package createBroken(File abiDir, Properties props) { - AndroidVersion version = null; - String abiType = abiDir.getName(); - String error = null; - IdDisplay tag = null; - - // Try to load the android version, tag & ABI from the sources.props. - // If we don't find them, it would explain why this package is broken. - if (props == null) { - error = String.format("Missing file %1$s", SdkConstants.FN_SOURCE_PROP); - } else { - try { - version = new AndroidVersion(props); - - tag = LocalSysImgPkgInfo.extractTagFromProps(props); - String abi = props.getProperty(PkgProps.SYS_IMG_ABI); - if (abi != null) { - abiType = abi; - } else { - error = String.format("Invalid file %1$s: Missing property %2$s", - SdkConstants.FN_SOURCE_PROP, - PkgProps.SYS_IMG_ABI); - } - } catch (AndroidVersionException e) { - error = String.format("Invalid file %1$s: %2$s", - SdkConstants.FN_SOURCE_PROP, - e.getMessage()); - } - } - - try { - // Try to parse the first number out of the platform folder name. - // Also try to parse the tag if not known yet. - // Folder structure should be: - // Tools < 22.6 / API < 20: sdk/system-images/android-N/abi/ - // Tools >=22.6 / API >=20: sdk/system-images/android-N/tag/abi/ - String[] segments = abiDir.getAbsolutePath().split(Pattern.quote(File.separator)); - int len = segments.length; - for (int i = len - 2; version == null && i >= 0; i--) { - if (SdkConstants.FD_SYSTEM_IMAGES.equals(segments[i])) { - if (version == null) { - String platform = segments[i+1]; - try { - platform = platform.replaceAll("[^0-9]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$ - int pos = platform.indexOf(' '); - if (pos >= 0) { - platform = platform.substring(0, pos); - } - int apiLevel = Integer.parseInt(platform); - version = new AndroidVersion(apiLevel, null /*codename*/); - } catch (Exception ignore) {} - } - if (tag == null && i+2 < len) { - // If we failed to find a tag id in the properties, check whether - // we can guess one from the system image folder path. It should - // match the limited tag id character set and not be one of the - // known ABIs. - String abiOrTag = segments[i+2].trim(); - if (abiOrTag.matches("[A-Za-z0-9_-]+")) { - if (Abi.getEnum(abiOrTag) == null) { - tag = new IdDisplay(abiOrTag, - LocalSysImgPkgInfo.tagIdToDisplay(abiOrTag)); - } - } - } - } - } - } catch (Exception ignore) {} - - String vendorId = getProperty(props, PkgProps.ADDON_VENDOR_ID, null); - String vendorDisp = getProperty(props, PkgProps.ADDON_VENDOR_DISPLAY, vendorId); - - StringBuilder sb = new StringBuilder("Broken "); - sb.append(getAbiDisplayNameInternal(abiType)).append(' '); - if (tag != null && !tag.getId().equals(SystemImage.DEFAULT_TAG.getId())) { - sb.append(tag).append(' '); - } - sb.append("System Image"); - if (vendorDisp != null) { - sb.append(", by ").append(vendorDisp); - } - if (version != null) { - sb.append(String.format(", API %1$s", version.getApiString())); - } - - String shortDesc = sb.toString(); - - if (error != null) { - sb.append('\n').append(error); - } - - String longDesc = sb.toString(); - - if (tag == null) { - // No tag? Use the default. - tag = SystemImage.DEFAULT_TAG; - } - assert tag != null; - - IPkgDesc desc = PkgDesc.Builder - .newSysImg(version != null ? version : new AndroidVersion(0, null), - tag, - abiType, - new MajorRevision(MajorRevision.MISSING_MAJOR_REV)) - .setDescriptionShort(shortDesc) - .create(); - - return new BrokenPackage(props, shortDesc, longDesc, - IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, - version==null ? IExactApiLevelDependency.API_LEVEL_INVALID : version.getApiLevel(), - abiDir.getAbsolutePath(), - desc); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - /** - * Save the properties of the current packages in the given {@link Properties} object. - * These properties will later be given to a constructor that takes a {@link Properties} object. - */ - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - mVersion.saveProperties(props); - props.setProperty(PkgProps.SYS_IMG_ABI, mAbi); - props.setProperty(PkgProps.SYS_IMG_TAG_ID, mTag.getId()); - props.setProperty(PkgProps.SYS_IMG_TAG_DISPLAY, mTag.getDisplay()); - - if (mAddonVendor != null) { - props.setProperty(PkgProps.ADDON_VENDOR_ID, mAddonVendor.getId()); - props.setProperty(PkgProps.ADDON_VENDOR_DISPLAY, mAddonVendor.getDisplay()); - } - } - - /** Returns the tag of the system-image. */ - @NonNull - public IdDisplay getTag() { - return mTag; - } - - /** Returns the ABI of the system-image. Cannot be null nor empty. */ - public String getAbi() { - return mAbi; - } - - /** Returns a display-friendly name for the ABI of the system-image. */ - public String getAbiDisplayName() { - return getAbiDisplayNameInternal(mAbi); - } - - private static String getAbiDisplayNameInternal(String abi) { - return abi.replace("armeabi", "ARM EABI") //$NON-NLS-1$ //$NON-NLS-2$ - .replace("arm64", "ARM 64") //$NON-NLS-1$ //$NON-NLS-2$ - .replace("x86", "Intel x86 Atom") //$NON-NLS-1$ //$NON-NLS-2$ - .replace("x86_64", "Intel x86_64 Atom") //$NON-NLS-1$ //$NON-NLS-2$ - .replace("mips", "MIPS") //$NON-NLS-1$ //$NON-NLS-2$ - .replace("-", " "); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Returns the version of the platform dependency of this package. - *

- * A system-image has the same {@link AndroidVersion} as the platform it depends on. - */ - @NonNull - @Override - public AndroidVersion getAndroidVersion() { - return mVersion; - } - - /** - * Returns true if the system-image belongs to a standard Android platform. - * In this case {@link #getAddonVendor()} returns null. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - StringBuilder sb = new StringBuilder("sys-img-"); //$NON-NLS-1$ - sb.append(getAbi()).append('-'); - if (!isPlatform()) { - sb.append("addon-"); - } - sb.append(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId()); - sb.append('-'); - if (!isPlatform()) { - sb.append(getAddonVendor().getId()).append('-'); - } - sb.append(getAndroidVersion().getApiString()); - - String s = sb.toString(); - s = s.toLowerCase(Locale.US).replaceAll("[^a-z0-9_.-]+", "_").replaceAll("_+", "_"); - return s; - - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s%2$s", ld, isObsolete() ? " (Obsolete)" : ""); - } - - boolean isDefaultTag = SystemImage.DEFAULT_TAG.equals(mTag); - return String.format("%1$s%2$s System Image%3$s", - isDefaultTag ? "" : (mTag.getDisplay() + " "), - getAbiDisplayName(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, %2$s API %3$s, revision %4$s%5$s", - ld, - mAddonVendor == null ? "Android" : mAddonVendor.getDisplay(), - mVersion.getApiString(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - boolean isDefaultTag = SystemImage.DEFAULT_TAG.equals(mTag); - return String.format("%1$s%2$s System Image, %3$s API %4$s, revision %5$s%6$s", - isDefaultTag ? "" : (mTag.getDisplay() + " "), - getAbiDisplayName(), - mAddonVendor == null ? "Android" : mAddonVendor.getDisplay(), - mVersion.getApiString(), - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a long description for an {@link IDescription}. - * - * The long description is whatever the XML contains for the {@code description} field, - * or the short description if the former is empty. - */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - s += String.format("\nRequires SDK Platform Android API %1$s", - mVersion.getApiString()); - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A system-image package is typically installed in SDK/systems/platform/tag/abi. - * The name needs to be sanitized to be acceptable as a directory name. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - File folder = new File(osSdkRoot, SdkConstants.FD_SYSTEM_IMAGES); - folder = new File(folder, AndroidTargetHash.getPlatformHashString(mVersion)); - - // Computes a folder directory using the sanitized tag & abi strings. - String tag = mTag.getId(); - tag = tag.toLowerCase(Locale.US); - tag = tag.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - tag = tag.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - tag = tag.replaceAll("-+", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - - folder = new File(folder, tag); - - String abi = mAbi; - abi = abi.toLowerCase(Locale.US); - abi = abi.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - abi = abi.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - abi = abi.replaceAll("-+", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - - folder = new File(folder, abi); - return folder; - } - - @Override - public boolean sameItemAs(Package pkg) { - if (pkg instanceof SystemImagePackage) { - SystemImagePackage newPkg = (SystemImagePackage)pkg; - - // check they are the same tag, abi and version. - return getTag().equals(newPkg.getTag()) && - getAbi().equals(newPkg.getAbi()) && - getAndroidVersion().equals(newPkg.getAndroidVersion()) && - (mAddonVendor == newPkg.mAddonVendor || - (mAddonVendor != null && mAddonVendor.equals(newPkg.mAddonVendor))); - } - - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((mAddonVendor == null) ? 0 : mAddonVendor.hashCode()); - result = prime * result + ((mTag == null) ? 0 : mTag.hashCode()); - result = prime * result + ((mAbi == null) ? 0 : mAbi.hashCode()); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof SystemImagePackage)) { - return false; - } - SystemImagePackage other = (SystemImagePackage) obj; - if (mAddonVendor == null) { - if (other.mAddonVendor != null) { - return false; - } - } else if (!mAddonVendor.equals(other.mAddonVendor)) { - return false; - } - if (mTag == null) { - if (other.mTag != null) { - return false; - } - } else if (!mTag.equals(other.mTag)) { - return false; - } - if (mAbi == null) { - if (other.mAbi != null) { - return false; - } - } else if (!mAbi.equals(other.mAbi)) { - return false; - } - if (mVersion == null) { - if (other.mVersion != null) { - return false; - } - } else if (!mVersion.equals(other.mVersion)) { - return false; - } - return true; - } - - /** - * For sys img packages, we want to add tag/abi to the sorting key - * before the revision number. - *

- * {@inheritDoc} - */ - @Override - protected String comparisonKey() { - String s = super.comparisonKey(); - int pos = s.indexOf("|r:"); //$NON-NLS-1$ - assert pos > 0; - s = s.substring(0, pos) + - "|vend:" + (mAddonVendor == null ? "" : mAddonVendor.getId()) + //$NON-NLS-1$ //$NON-NLS-2$ - "|tag:" + getTag().getId() + //$NON-NLS-1$ - "|abi:" + getAbiDisplayName() + //$NON-NLS-1$ - s.substring(pos); - return s; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ToolPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ToolPackage.java deleted file mode 100644 index 1b8b3b83..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/packages/ToolPackage.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.packages; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.SdkManager; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; - -import org.w3c.dom.Node; - -import java.io.File; -import java.util.Map; -import java.util.Properties; - -/** - * Represents a tool XML node in an SDK repository. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ToolPackage extends FullRevisionPackage implements IMinPlatformToolsDependency { - - /** The value returned by {@link ToolPackage#installId()}. */ - public static final String INSTALL_ID = "tools"; //$NON-NLS-1$ - /** The value returned by {@link ToolPackage#installId()}. */ - private static final String INSTALL_ID_PREVIEW = "tools-preview"; //$NON-NLS-1$ - - /** - * The minimal revision of the platform-tools package required by this package - * or {@link #MIN_PLATFORM_TOOLS_REV_INVALID} if the value was missing. - */ - private final FullRevision mMinPlatformToolsRevision; - - private final IPkgDesc mPkgDesc; - - /** - * Creates a new tool package from the attributes and elements of the given XML node. - * This constructor should throw an exception if the package cannot be created. - * - * @param source The {@link SdkSource} where this is loaded from. - * @param packageNode The XML element being parsed. - * @param nsUri The namespace URI of the originating XML document, to be able to deal with - * parameters that vary according to the originating XML schema. - * @param licenses The licenses loaded from the XML originating document. - */ - public ToolPackage(SdkSource source, - Node packageNode, - String nsUri, - Map licenses) { - super(source, packageNode, nsUri, licenses); - - mMinPlatformToolsRevision = PackageParserUtils.parseFullRevisionElement( - PackageParserUtils.findChildElement(packageNode, - SdkRepoConstants.NODE_MIN_PLATFORM_TOOLS_REV)); - - if (mMinPlatformToolsRevision.equals(MIN_PLATFORM_TOOLS_REV_INVALID)) { - // This revision number is mandatory starting with sdk-repository-3.xsd - // and did not exist before. Complain if the URI has level >= 3. - if (SdkRepoConstants.versionGreaterOrEqualThan(nsUri, 3)) { - throw new IllegalArgumentException( - String.format("Missing %1$s element in %2$s package", - SdkRepoConstants.NODE_MIN_PLATFORM_TOOLS_REV, - SdkRepoConstants.NODE_PLATFORM_TOOL)); - } - } - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newTool(getRevision(), mMinPlatformToolsRevision)) - .create(); - } - - /** - * Manually create a new package with one archive and the given attributes or properties. - * This is used to create packages from local directories in which case there must be - * one archive which URL is the actual target location. - *

- * By design, this creates a package with one and only one archive. - */ - public static Package create( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - return new ToolPackage(source, props, revision, license, description, - descUrl, archiveOsPath); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected ToolPackage( - SdkSource source, - Properties props, - int revision, - String license, - String description, - String descUrl, - String archiveOsPath) { - super(source, - props, - revision, - license, - description, - descUrl, - archiveOsPath); - - // Setup min-platform-tool - String revStr = getProperty(props, PkgProps.MIN_PLATFORM_TOOLS_REV, null); - - FullRevision rev = MIN_PLATFORM_TOOLS_REV_INVALID; - if (revStr != null) { - try { - rev = FullRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - mMinPlatformToolsRevision = rev; - - mPkgDesc = setDescriptions(PkgDesc.Builder - .newTool(getRevision(), mMinPlatformToolsRevision)) - .create(); - } - - @Override - @NonNull - public IPkgDesc getPkgDesc() { - return mPkgDesc; - } - - @Override - public FullRevision getMinPlatformToolsRevision() { - return mMinPlatformToolsRevision; - } - - /** - * Returns a string identifier to install this package from the command line. - * For tools, we use "tools" or "tools-preview" since this package is unique. - *

- * {@inheritDoc} - */ - @Override - public String installId() { - if (getRevision().isPreview()) { - return INSTALL_ID_PREVIEW; - } else { - return INSTALL_ID; - } - } - - /** - * Returns a description of this package that is suitable for a list display. - *

- * {@inheritDoc} - */ - @Override - public String getListDescription() { - String ld = getListDisplay(); - return String.format("%1$s%2$s", - ld.isEmpty() ? "Android SDK Tools" : ld, - isObsolete() ? " (Obsolete)" : ""); - } - - /** - * Returns a short description for an {@link IDescription}. - */ - @Override - public String getShortDescription() { - String ld = getListDisplay(); - if (!ld.isEmpty()) { - return String.format("%1$s, revision %2$s%3$s", - ld, - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return String.format("Android SDK Tools, revision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - /** Returns a long description for an {@link IDescription}. */ - @Override - public String getLongDescription() { - String s = getDescription(); - if (s == null || s.isEmpty()) { - s = getShortDescription(); - } - - if (s.indexOf("revision") == -1) { - s += String.format("\nRevision %1$s%2$s", - getRevision().toShortString(), - isObsolete() ? " (Obsolete)" : ""); - } - - return s; - } - - /** - * Computes a potential installation folder if an archive of this package were - * to be installed right away in the given SDK root. - *

- * A "tool" package should always be located in SDK/tools. - * - * @param osSdkRoot The OS path of the SDK root folder. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @return A new {@link File} corresponding to the directory to use to install this package. - */ - @Override - public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { - return new File(osSdkRoot, SdkConstants.FD_TOOLS); - } - - /** - * Check whether 2 tool packages are the same and have the - * same preview bit. - */ - @Override - public boolean sameItemAs(Package pkg) { - return sameItemAs(pkg, PreviewComparison.COMPARE_TYPE); - } - - @Override - public boolean sameItemAs(Package pkg, PreviewComparison comparePreview) { - // only one tool package so any platform-tool package is the same item. - if (pkg instanceof ToolPackage) { - switch (comparePreview) { - case IGNORE: - return true; - - case COMPARE_NUMBER: - // Voluntary break-through. - case COMPARE_TYPE: - // There's only one tool so the preview number doesn't matter; - // however previews can only match previews by default so both cases - // are treated the same. - return pkg.getRevision().isPreview() == getRevision().isPreview(); - } - } - return false; - } - - @Override - public void saveProperties(Properties props) { - super.saveProperties(props); - - if (!getMinPlatformToolsRevision().equals(MIN_PLATFORM_TOOLS_REV_INVALID)) { - props.setProperty(PkgProps.MIN_PLATFORM_TOOLS_REV, - getMinPlatformToolsRevision().toShortString()); - } - } - - /** - * The tool package executes tools/lib/post_tools_install[.bat|.sh] - * {@inheritDoc} - */ - @Override - public void postInstallHook(Archive archive, final ITaskMonitor monitor, File installFolder) { - super.postInstallHook(archive, monitor, installFolder); - - if (installFolder == null) { - return; - } - - File libDir = new File(installFolder, SdkConstants.FD_LIB); - if (!libDir.isDirectory()) { - return; - } - - String scriptName = "post_tools_install"; //$NON-NLS-1$ - String shell = ""; //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - shell = "cmd.exe /c "; //$NON-NLS-1$ - scriptName += ".bat"; //$NON-NLS-1$ - } else { - scriptName += ".sh"; //$NON-NLS-1$ - } - - File scriptFile = new File(libDir, scriptName); - if (!scriptFile.isFile()) { - return; - } - - int status = -1; - - try { - Process proc = Runtime.getRuntime().exec( - shell + scriptName, // command - null, // environment - libDir); // working dir - - final String tag = scriptName; - status = GrabProcessOutput.grabProcessOutput( - proc, - Wait.WAIT_FOR_PROCESS, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - if (line != null) { - monitor.log("[%1$s] %2$s", tag, line); - } - } - - @Override - public void err(@Nullable String line) { - if (line != null) { - monitor.logError("[%1$s] Error: %2$s", tag, line); - } - } - }); - - } catch (Exception e) { - monitor.logError("Exception: %s", e.toString()); - } - - if (status != 0) { - monitor.logError("Failed to execute %s", scriptName); - return; - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result - + ((mMinPlatformToolsRevision == null) ? 0 : mMinPlatformToolsRevision.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof ToolPackage)) { - return false; - } - ToolPackage other = (ToolPackage) obj; - if (mMinPlatformToolsRevision == null) { - if (other.mMinPlatformToolsRevision != null) { - return false; - } - } else if (!mMinPlatformToolsRevision.equals(other.mMinPlatformToolsRevision)) { - return false; - } - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkAddonSource.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkAddonSource.java deleted file mode 100644 index a77b128e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkAddonSource.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.sources; - -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.repository.SdkAddonConstants; - -import org.w3c.dom.Document; - -import java.io.InputStream; - - -/** - * An sdk-addon source, i.e. a download site for addons and extra packages. - * A repository describes one or more {@link Package}s available for download. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkAddonSource extends SdkSource { - - /** - * Constructs a new source for the given repository URL. - * @param url The source URL. Cannot be null. If the URL ends with a /, the default - * addon.xml filename will be appended automatically. - * @param uiName The UI-visible name of the source. Can be null. - */ - public SdkAddonSource(String url, String uiName) { - super(url, uiName); - } - - /** - * Returns true if this is an addon source. - * We only load addons and extras from these sources. - */ - @Override - public boolean isAddonSource() { - return true; - } - - /** - * Returns true if this is a system-image source. - * We only load system-images from these sources. - */ - @Override - public boolean isSysImgSource() { - return false; - } - - @Override - protected String[] getDefaultXmlFileUrls() { - return new String[] { SdkAddonConstants.URL_DEFAULT_FILENAME }; - } - - @Override - protected int getNsLatestVersion() { - return SdkAddonConstants.NS_LATEST_VERSION; - } - - @Override - protected String getNsUri() { - return SdkAddonConstants.NS_URI; - } - - @Override - protected String getNsPattern() { - return SdkAddonConstants.NS_PATTERN; - } - - @Override - protected String getSchemaUri(int version) { - return SdkAddonConstants.getSchemaUri(version); - } - - @Override - protected String getRootElementName() { - return SdkAddonConstants.NODE_SDK_ADDON; - } - - @Override - protected InputStream getXsdStream(int version) { - return SdkAddonConstants.getXsdStream(version); - } - - /** - * This kind of schema does not support forward-evolution of the <tool> element. - * - * @param xml The input XML stream. Can be null. - * @return Always null. - * @null This implementation always return null. - */ - @Override - protected Document findAlternateToolsXml(@Nullable InputStream xml) { - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkRepoSource.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkRepoSource.java deleted file mode 100644 index 3d2efb50..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkRepoSource.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.sources; - -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.archives.ArchFilter; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PackageParserUtils; -import com.android.sdklib.repository.RepoConstants; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.Text; -import org.xml.sax.ErrorHandler; - -import java.io.IOException; -import java.io.InputStream; -import java.util.regex.Pattern; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - - -/** - * An sdk-repository source, i.e. a download site. - * A repository describes one or more {@link Package}s available for download. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkRepoSource extends SdkSource { - - /** - * Constructs a new source for the given repository URL. - * @param url The source URL. Cannot be null. If the URL ends with a /, the default - * repository.xml filename will be appended automatically. - * @param uiName The UI-visible name of the source. Can be null. - */ - public SdkRepoSource(String url, String uiName) { - super(url, uiName); - } - - /** - * Returns true if this is an addon source. - * We only load addons and extras from these sources. - */ - @Override - public boolean isAddonSource() { - return false; - } - - /** - * Returns true if this is a system-image source. - * We only load system-images from these sources. - */ - @Override - public boolean isSysImgSource() { - return false; - } - - private static String[] sDefaults = null; // lazily allocated in getDefaultXmlFileUrls - - @Override - protected String[] getDefaultXmlFileUrls() { - if (sDefaults == null) { - String[] values = new String[SdkRepoConstants.NS_LATEST_VERSION - - SdkRepoConstants.NS_SERVER_MIN_VERSION - + 2]; - int k = 0; - for (int i = SdkRepoConstants.NS_LATEST_VERSION; - i >= SdkRepoConstants.NS_SERVER_MIN_VERSION; - i--) { - values[k++] = String.format(SdkRepoConstants.URL_FILENAME_PATTERN, i); - } - values[k++] = SdkRepoConstants.URL_DEFAULT_FILENAME; - assert k == values.length; - sDefaults = values; - } - - return sDefaults; - } - - @Override - protected int getNsLatestVersion() { - return SdkRepoConstants.NS_LATEST_VERSION; - } - - @Override - protected String getNsUri() { - return SdkRepoConstants.NS_URI; - } - - @Override - protected String getNsPattern() { - return SdkRepoConstants.NS_PATTERN; - } - - @Override - protected String getSchemaUri(int version) { - return SdkRepoConstants.getSchemaUri(version); - } - - @Override - protected String getRootElementName() { - return SdkRepoConstants.NODE_SDK_REPOSITORY; - } - - @Override - protected InputStream getXsdStream(int version) { - return SdkRepoConstants.getXsdStream(version); - } - - /** - * The purpose of this method is to support forward evolution of our schema. - *

- * At this point, we know that xml does not point to any schema that this version of - * the tool knows how to process, so it's not one of the possible 1..N versions of our - * XSD schema. - *

- * We thus try to interpret the byte stream as a possible XML stream. It may not be - * one at all in the first place. If it looks anything line an XML schema, we try to - * find its <tool> and the <platform-tools> elements. If we find any, - * we recreate a suitable document that conforms to what we expect from our XSD schema - * with only those elements. - *

- * To be valid, the <tool> and the <platform-tools> elements must have at - * least one <archive> compatible with this platform. - *

- * Starting the sdk-repository schema v3, <tools> has a <min-platform-tools-rev> - * node, so technically the corresponding XML schema will be usable only if there's a - * <platform-tools> with the request revision number. We don't enforce that here, as - * this is done at install time. - *

- * If we don't find anything suitable, we drop the whole thing. - * - * @param xml The input XML stream. Can be null. - * @return Either a new XML document conforming to our schema with at least one <tool> - * and <platform-tools> element or null. - * @throws IOException if InputStream.reset() fails - * @null Can return null on failure. - */ - @Override - protected Document findAlternateToolsXml(@Nullable InputStream xml) throws IOException { - return findAlternateToolsXml(xml, null /*errorHandler*/); - } - - /** - * An alternate version of {@link #findAlternateToolsXml(InputStream)} that allows - * the caller to specify the XML error handler. The default from the underlying Java - * XML Xerces parser will dump to stdout/stderr, which is not convenient during unit tests. - * - * @param xml The input XML stream. Can be null. - * @param errorHandler An optional XML error handler. If null, the default will be used. - * @return Either a new XML document conforming to our schema with at least one <tool> - * and <platform-tools> element or null. - * @throws IOException if InputStream.reset() fails - * @null Can return null on failure. - * @see #findAlternateToolsXml(InputStream) findAlternateToolsXml() provides more details. - */ - protected Document findAlternateToolsXml( - @Nullable InputStream xml, - @Nullable ErrorHandler errorHandler) - throws IOException { - if (xml == null) { - return null; - } - - // Reset the stream if it supports that operation. - assert xml.markSupported(); - xml.reset(); - - // Get an XML document - - Document oldDoc = null; - Document newDoc = null; - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(false); - factory.setValidating(false); - - // Parse the old document using a non namespace aware builder - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - - if (errorHandler != null) { - builder.setErrorHandler(errorHandler); - } - - oldDoc = builder.parse(xml); - - // Prepare a new document using a namespace aware builder - factory.setNamespaceAware(true); - builder = factory.newDocumentBuilder(); - newDoc = builder.newDocument(); - - } catch (Exception e) { - // Failed to get builder factor - // Failed to create XML document builder - // Failed to parse XML document - // Failed to read XML document - } - - if (oldDoc == null || newDoc == null) { - return null; - } - - - // Check the root element is an XML with at least the following properties: - // - // - // Note that we don't have namespace support enabled, we just do it manually. - - Pattern nsPattern = Pattern.compile(getNsPattern()); - - Node oldRoot = null; - String prefix = null; - for (Node child = oldDoc.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - prefix = null; - String name = child.getNodeName(); - int pos = name.indexOf(':'); - if (pos > 0 && pos < name.length() - 1) { - prefix = name.substring(0, pos); - name = name.substring(pos + 1); - } - if (SdkRepoConstants.NODE_SDK_REPOSITORY.equals(name)) { - NamedNodeMap attrs = child.getAttributes(); - String xmlns = "xmlns"; //$NON-NLS-1$ - if (prefix != null) { - xmlns += ":" + prefix; //$NON-NLS-1$ - } - Node attr = attrs.getNamedItem(xmlns); - if (attr != null) { - String uri = attr.getNodeValue(); - if (uri != null && nsPattern.matcher(uri).matches()) { - oldRoot = child; - break; - } - } - } - } - } - - // we must have found the root node, and it must have an XML namespace prefix. - if (oldRoot == null || prefix == null || prefix.isEmpty()) { - return null; - } - - final String ns = getNsUri(); - Element newRoot = newDoc.createElementNS(ns, getRootElementName()); - newRoot.setPrefix(prefix); - newDoc.appendChild(newRoot); - int numTool = 0; - - // Find any inner or nodes and extract their required parameters - - String[] elementNames = { - SdkRepoConstants.NODE_TOOL, - SdkRepoConstants.NODE_PLATFORM_TOOL, - SdkRepoConstants.NODE_LICENSE - }; - - Element element = null; - while ((element = findChild(oldRoot, element, prefix, elementNames)) != null) { - boolean isElementValid = false; - - String name = element.getLocalName(); - if (name == null) { - name = element.getNodeName(); - - int pos = name.indexOf(':'); - if (pos > 0 && pos < name.length() - 1) { - name = name.substring(pos + 1); - } - } - - // To be valid, the tool or platform-tool element must have: - // - a element with a number - // - a element with a number for a element - // - an element with one or more elements inside - // - one of the elements must have an "os" and "arch" attributes - // compatible with the current platform. Only keep the first such element found. - // - the element must contain a , a and a . - // - none of the above for a license element - - if (SdkRepoConstants.NODE_LICENSE.equals(name)) { - isElementValid = true; - - } else { - try { - Node revision = findChild(element, null, prefix, RepoConstants.NODE_REVISION); - Node archives = findChild(element, null, prefix, RepoConstants.NODE_ARCHIVES); - - if (revision == null || archives == null) { - continue; - } - - // check revision contains a number - try { - String content = revision.getTextContent(); - content = content.trim(); - int rev = Integer.parseInt(content); - if (rev < 1) { - continue; - } - } catch (NumberFormatException ignore) { - continue; - } - - if (SdkRepoConstants.NODE_TOOL.equals(name)) { - Node minPTRev = findChild(element, null, prefix, - RepoConstants.NODE_MIN_PLATFORM_TOOLS_REV); - - if (minPTRev == null) { - continue; - } - - // check min-platform-tools-rev contains a number - try { - String content = minPTRev.getTextContent(); - content = content.trim(); - int rev = Integer.parseInt(content); - if (rev < 1) { - continue; - } - } catch (NumberFormatException ignore) { - continue; - } - } - - Node archive = null; - while ((archive = findChild(archives, - archive, - prefix, - RepoConstants.NODE_ARCHIVE)) != null) { - try { - ArchFilter af = PackageParserUtils.parseArchFilter(archive); - if (af == null || !af.isCompatibleWith(ArchFilter.getCurrent())) { - continue; - } - - Node node = findChild(archive, null, prefix, RepoConstants.NODE_URL); - String url = node == null ? null : node.getTextContent().trim(); - if (url == null || url.isEmpty()) { - continue; - } - - node = findChild(archive, null, prefix, RepoConstants.NODE_SIZE); - long size = 0; - try { - size = Long.parseLong(node.getTextContent()); - } catch (Exception e) { - // pass - } - if (size < 1) { - continue; - } - - node = findChild(archive, null, prefix, RepoConstants.NODE_CHECKSUM); - // double check that the checksum element contains a type=sha1 attribute - if (node == null) { - continue; - } - NamedNodeMap attrs = node.getAttributes(); - Node typeNode = attrs.getNamedItem(RepoConstants.ATTR_TYPE); - if (typeNode == null || - !RepoConstants.ATTR_TYPE.equals(typeNode.getNodeName()) || - !RepoConstants.SHA1_TYPE.equals(typeNode.getNodeValue())) { - continue; - } - String sha1 = node == null ? null : node.getTextContent().trim(); - if (sha1 == null || - sha1.length() != RepoConstants.SHA1_CHECKSUM_LEN) { - continue; - } - - isElementValid = true; - - } catch (Exception ignore1) { - // For debugging it is useful to re-throw the exception. - // For end-users, not so much. It would be nice to make it - // happen automatically during unit tests. - if (System.getenv("TESTING") != null || - System.getProperty("THROW_DEEP_EXCEPTION_DURING_TESTING") != null) { - throw new RuntimeException(ignore1); - } - } - } // while - } catch (Exception ignore2) { - // For debugging it is useful to re-throw the exception. - // For end-users, not so much. It would be nice to make it - // happen automatically during unit tests. - if (System.getenv("TESTING") != null || - System.getProperty("THROW_DEEP_EXCEPTION_DURING_TESTING") != null) { - throw new RuntimeException(ignore2); - } - } - } - - if (isElementValid) { - duplicateNode(newRoot, element, SdkRepoConstants.NS_URI, prefix); - numTool++; - } - } // while - - return numTool > 0 ? newDoc : null; - } - - /** - * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given - * element child in a root XML node. - */ - private Element findChild(Node rootNode, Node after, String prefix, String[] nodeNames) { - for (int i = 0; i < nodeNames.length; i++) { - if (nodeNames[i].indexOf(':') < 0) { - nodeNames[i] = prefix + ":" + nodeNames[i]; - } - } - Node child = after == null ? rootNode.getFirstChild() : after.getNextSibling(); - for(; child != null; child = child.getNextSibling()) { - if (child.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - for (String nodeName : nodeNames) { - if (nodeName.equals(child.getNodeName())) { - return (Element) child; - } - } - } - return null; - } - - /** - * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given - * element child in a root XML node. - */ - private Node findChild(Node rootNode, Node after, String prefix, String nodeName) { - return findChild(rootNode, after, prefix, new String[] { nodeName }); - } - - /** - * Helper method used by {@link #findAlternateToolsXml(InputStream)} to duplicate a node - * and attach it to the given root in the new document. - */ - private Element duplicateNode(Element newRootNode, Element oldNode, - String namespaceUri, String prefix) { - // The implementation here is more or less equivalent to - // - // newRoot.appendChild(newDoc.importNode(oldNode, deep=true)) - // - // except we can't just use importNode() since we need to deal with the fact - // that the old document is not namespace-aware yet the new one is. - - Document newDoc = newRootNode.getOwnerDocument(); - Element newNode = null; - - String nodeName = oldNode.getNodeName(); - int pos = nodeName.indexOf(':'); - if (pos > 0 && pos < nodeName.length() - 1) { - nodeName = nodeName.substring(pos + 1); - newNode = newDoc.createElementNS(namespaceUri, nodeName); - newNode.setPrefix(prefix); - } else { - newNode = newDoc.createElement(nodeName); - } - - newRootNode.appendChild(newNode); - - // Merge in all the attributes - NamedNodeMap attrs = oldNode.getAttributes(); - for (int i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); - Attr newAttr = null; - - String attrName = attr.getNodeName(); - pos = attrName.indexOf(':'); - if (pos > 0 && pos < attrName.length() - 1) { - attrName = attrName.substring(pos + 1); - newAttr = newDoc.createAttributeNS(namespaceUri, attrName); - newAttr.setPrefix(prefix); - } else { - newAttr = newDoc.createAttribute(attrName); - } - - newAttr.setNodeValue(attr.getNodeValue()); - - if (pos > 0) { - newNode.getAttributes().setNamedItemNS(newAttr); - } else { - newNode.getAttributes().setNamedItem(newAttr); - } - } - - // Merge all child elements and texts - for (Node child = oldNode.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - duplicateNode(newNode, (Element) child, namespaceUri, prefix); - - } else if (child.getNodeType() == Node.TEXT_NODE) { - Text newText = newDoc.createTextNode(child.getNodeValue()); - newNode.appendChild(newText); - } - } - - return newNode; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSource.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSource.java deleted file mode 100644 index 54ebd340..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSource.java +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.sources; - -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.io.NonClosingInputStream; -import com.android.io.NonClosingInputStream.CloseBehavior; -import com.android.sdklib.internal.repository.CanceledByUserException; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.internal.repository.packages.BuildToolPackage; -import com.android.sdklib.internal.repository.packages.DocPackage; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SamplePackage; -import com.android.sdklib.internal.repository.packages.SourcePackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.repository.RepoConstants; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; - -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.net.ssl.SSLKeyException; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; - -/** - * An sdk-addon or sdk-repository source, i.e. a download site. - * It may be a full repository or an add-on only repository. - * A repository describes one or {@link Package}s available for download. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public abstract class SdkSource implements IDescription, Comparable { - - private String mUrl; - - private Package[] mPackages; - private String mDescription; - private String mFetchError; - private final String mUiName; - - private static final SdkSourceProperties sSourcesProps = new SdkSourceProperties(); - - /** - * Constructs a new source for the given repository URL. - * @param url The source URL. Cannot be null. If the URL ends with a /, the default - * repository.xml filename will be appended automatically. - * @param uiName The UI-visible name of the source. Can be null. - */ - public SdkSource(String url, String uiName) { - - // URLs should not be null and should not have whitespace. - if (url == null) { - url = ""; - } - url = url.trim(); - - // if the URL ends with a /, it must be "directory" resource, - // in which case we automatically add the default file that will - // looked for. This way it will be obvious to the user which - // resource we are actually trying to fetch. - if (url.endsWith("/")) { //$NON-NLS-1$ - String[] names = getDefaultXmlFileUrls(); - if (names.length > 0) { - url += names[0]; - } - } - - if (uiName == null) { - uiName = sSourcesProps.getProperty(SdkSourceProperties.KEY_NAME, url, null); - } else { - sSourcesProps.setProperty(SdkSourceProperties.KEY_NAME, url, uiName); - } - - mUrl = url; - mUiName = uiName; - setDefaultDescription(); - } - - /** - * Returns true if this is an addon source. - * We only load addons and extras from these sources. - */ - public abstract boolean isAddonSource(); - - /** - * Returns true if this is a system-image source. - * We only load system-images from these sources. - */ - public abstract boolean isSysImgSource(); - - - /** - * Returns the basename of the default URLs to try to download the - * XML manifest. - * E.g. this is typically SdkRepoConstants.URL_DEFAULT_XML_FILE - * or SdkAddonConstants.URL_DEFAULT_XML_FILE - */ - protected abstract String[] getDefaultXmlFileUrls(); - - /** Returns SdkRepoConstants.NS_LATEST_VERSION or SdkAddonConstants.NS_LATEST_VERSION. */ - protected abstract int getNsLatestVersion(); - - /** Returns SdkRepoConstants.NS_URI or SdkAddonConstants.NS_URI. */ - protected abstract String getNsUri(); - - /** Returns SdkRepoConstants.NS_PATTERN or SdkAddonConstants.NS_PATTERN. */ - protected abstract String getNsPattern(); - - /** Returns SdkRepoConstants.getSchemaUri() or SdkAddonConstants.getSchemaUri(). */ - protected abstract String getSchemaUri(int version); - - /* Returns SdkRepoConstants.NODE_SDK_REPOSITORY or SdkAddonConstants.NODE_SDK_ADDON. */ - protected abstract String getRootElementName(); - - /** Returns SdkRepoConstants.getXsdStream() or SdkAddonConstants.getXsdStream(). */ - protected abstract InputStream getXsdStream(int version); - - /** - * In case we fail to load an XML, examine the XML to see if it matches a future - * schema that as at least a tools node that we could load to update the - * SDK Manager. - * - * @param xml The input XML stream. Can be null. - * @return Null on failure, otherwise returns an XML DOM with just the tools we - * need to update this SDK Manager. - * @null Can return null on failure. - */ - protected abstract Document findAlternateToolsXml(@Nullable InputStream xml) - throws IOException; - - /** - * Two repo source are equal if they have the same URL. - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof SdkSource) { - SdkSource rs = (SdkSource) obj; - return rs.getUrl().equals(this.getUrl()); - } - return false; - } - - @Override - public int hashCode() { - return mUrl.hashCode(); - } - - /** - * Implementation of the {@link Comparable} interface. - * Simply compares the URL using the string's default ordering. - */ - @Override - public int compareTo(SdkSource rhs) { - return this.getUrl().compareTo(rhs.getUrl()); - } - - /** - * Returns the UI-visible name of the source. Can be null. - */ - public String getUiName() { - return mUiName; - } - - /** Returns the URL of the XML file for this source. */ - public String getUrl() { - return mUrl; - } - - /** - * Returns the list of known packages found by the last call to load(). - * This is null when the source hasn't been loaded yet -- caller should - * then call {@link #load} to load the packages. - */ - public Package[] getPackages() { - return mPackages; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void setPackages(Package[] packages) { - mPackages = packages; - - if (mPackages != null) { - // Order the packages. - Arrays.sort(mPackages, null); - } - } - - /** - * Clear the internal packages list. After this call, {@link #getPackages()} will return - * null till load() is called. - */ - public void clearPackages() { - setPackages(null); - } - - /** - * Indicates if the source is enabled. - *

- * A 3rd-party add-on source can be disabled by the user to prevent from loading it. - * - * @return True if the source is enabled (default is true). - */ - public boolean isEnabled() { - // A URL is enabled if it's not in the disabled list. - return sSourcesProps.getProperty(SdkSourceProperties.KEY_DISABLED, mUrl, null) == null; - } - - /** - * Changes whether the source is marked as enabled. - *

- * When changing the enable state, the current package list is purged - * and the next {@code load} will either return an empty list (if disabled) or - * the actual package list (if enabled.) - * - * @param enabled True for the source to be enabled (can be loaded), false otherwise. - */ - public void setEnabled(boolean enabled) { - if (enabled != isEnabled()) { - // First we clear the current package list, which will force the - // next load() to actually set the package list as desired. - clearPackages(); - - sSourcesProps.setProperty(SdkSourceProperties.KEY_DISABLED, mUrl, - enabled ? null /*remove*/ : "disabled"); //$NON-NLS-1$ - } - } - - /** - * Returns the short description of the source, if not null. - * Otherwise returns the default Object toString result. - *

- * This is mostly helpful for debugging. - * For UI display, use the {@link IDescription} interface. - */ - @Override - public String toString() { - String s = getShortDescription(); - if (s != null) { - return s; - } - return super.toString(); - } - - @Override - public String getShortDescription() { - - if (mUiName != null && !mUiName.isEmpty()) { - - String host = "malformed URL"; - - try { - URL u = new URL(mUrl); - host = u.getHost(); - } catch (MalformedURLException e) { - } - - return String.format("%1$s (%2$s)", mUiName, host); - - } - return mUrl; - } - - @Override - public String getLongDescription() { - // Note: in a normal workflow, mDescription is filled by setDefaultDescription(). - // However for packages made by unit tests or such, this can be null. - return mDescription == null ? "" : mDescription; //$NON-NLS-1$ - } - - /** - * Returns the last fetch error description. - * If there was no error, returns null. - */ - public String getFetchError() { - return mFetchError; - } - - /** - * Tries to fetch the repository index for the given URL and updates the package list. - * When a source is disabled, this create an empty non-null package list. - *

- * Callers can get the package list using {@link #getPackages()} after this. It will be - * null in case of error, in which case {@link #getFetchError()} can be used to an - * error message. - */ - public void load(DownloadCache cache, ITaskMonitor monitor, boolean forceHttp) { - - setDefaultDescription(); - monitor.setProgressMax(7); - - if (!isEnabled()) { - setPackages(new Package[0]); - mDescription += "\nSource is disabled."; - monitor.incProgress(7); - return; - } - - String url = mUrl; - if (forceHttp) { - url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - monitor.setDescription("Fetching URL: %1$s", url); - monitor.incProgress(1); - - mFetchError = null; - Boolean[] validatorFound = new Boolean[] { Boolean.FALSE }; - String[] validationError = new String[] { null }; - Exception[] exception = new Exception[] { null }; - Document validatedDoc = null; - boolean usingAlternateXml = false; - boolean usingAlternateUrl = false; - String validatedUri = null; - - String[] defaultNames = getDefaultXmlFileUrls(); - String firstDefaultName = defaultNames.length > 0 ? defaultNames[0] : ""; - - InputStream xml = fetchXmlUrl(url, cache, monitor.createSubMonitor(1), exception); - if (xml != null) { - int version = getXmlSchemaVersion(xml); - if (version == 0) { - closeStream(xml); - xml = null; - } - } - - // FIXME: this is a quick fix to support an alternate upgrade path. - // The whole logic below needs to be updated. - if (xml == null && defaultNames.length > 0) { - ITaskMonitor subMonitor = monitor.createSubMonitor(1); - subMonitor.setProgressMax(defaultNames.length); - - String baseUrl = url; - if (!baseUrl.endsWith("/")) { - int pos = baseUrl.lastIndexOf('/'); - if (pos > 0) { - baseUrl = baseUrl.substring(0, pos + 1); - } - } - - for (String name : defaultNames) { - String newUrl = baseUrl + name; - if (newUrl.equals(url)) { - continue; - } - xml = fetchXmlUrl(newUrl, cache, subMonitor.createSubMonitor(1), exception); - if (xml != null) { - int version = getXmlSchemaVersion(xml); - if (version == 0) { - closeStream(xml); - xml = null; - } else { - url = newUrl; - subMonitor.incProgress( - subMonitor.getProgressMax() - subMonitor.getProgress()); - break; - } - } - } - } else { - monitor.incProgress(1); - } - - // If the original URL can't be fetched - // and the URL doesn't explicitly end with our filename - // and it wasn't an HTTP authentication operation canceled by the user - // then make another tentative after changing the URL. - if (xml == null - && !url.endsWith(firstDefaultName) - && !(exception[0] instanceof CanceledByUserException)) { - if (!url.endsWith("/")) { //$NON-NLS-1$ - url += "/"; //$NON-NLS-1$ - } - url += firstDefaultName; - - xml = fetchXmlUrl(url, cache, monitor.createSubMonitor(1), exception); - usingAlternateUrl = true; - } else { - monitor.incProgress(1); - } - - // FIXME this needs to revisited. - if (xml != null) { - monitor.setDescription("Validate XML: %1$s", url); - - ITaskMonitor subMonitor = monitor.createSubMonitor(2); - subMonitor.setProgressMax(2); - for (int tryOtherUrl = 0; tryOtherUrl < 2; tryOtherUrl++) { - // Explore the XML to find the potential XML schema version - int version = getXmlSchemaVersion(xml); - - if (version >= 1 && version <= getNsLatestVersion()) { - // This should be a version we can handle. Try to validate it - // and report any error as invalid XML syntax, - - String uri = validateXml(xml, url, version, validationError, validatorFound); - if (uri != null) { - // Validation was successful - validatedDoc = getDocument(xml, monitor); - validatedUri = uri; - - if (usingAlternateUrl && validatedDoc != null) { - // If the second tentative succeeded, indicate it in the console - // with the URL that worked. - monitor.log("Repository found at %1$s", url); - - // Keep the modified URL - mUrl = url; - } - } else if (validatorFound[0].equals(Boolean.FALSE)) { - // Validation failed because this JVM lacks a proper XML Validator - mFetchError = validationError[0]; - } else { - // We got a validator but validation failed. We know there's - // what looks like a suitable root element with a suitable XMLNS - // so it must be a genuine error of an XML not conforming to the schema. - } - } else if (version > getNsLatestVersion()) { - // The schema used is more recent than what is supported by this tool. - // Tell the user to upgrade, pointing him to the right version of the tool - // package. - - try { - validatedDoc = findAlternateToolsXml(xml); - } catch (IOException e) { - // Failed, will be handled below. - } - if (validatedDoc != null) { - validationError[0] = null; // remove error from XML validation - validatedUri = getNsUri(); - usingAlternateXml = true; - } - - } else if (version < 1 && tryOtherUrl == 0 && !usingAlternateUrl) { - // This is obviously not one of our documents. - mFetchError = String.format( - "Failed to validate the XML for the repository at URL '%1$s'", - url); - - // If we haven't already tried the alternate URL, let's do it now. - // We don't capture any fetch exception that happen during the second - // fetch in order to avoid hiding any previous fetch errors. - if (!url.endsWith(firstDefaultName)) { - if (!url.endsWith("/")) { //$NON-NLS-1$ - url += "/"; //$NON-NLS-1$ - } - url += firstDefaultName; - - closeStream(xml); - xml = fetchXmlUrl(url, cache, subMonitor.createSubMonitor(1), - null /* outException */); - subMonitor.incProgress(1); - // Loop to try the alternative document - if (xml != null) { - usingAlternateUrl = true; - continue; - } - } - } else if (version < 1 && usingAlternateUrl && mFetchError == null) { - // The alternate URL is obviously not a valid XML either. - // We only report the error if we failed to produce one earlier. - mFetchError = String.format( - "Failed to validate the XML for the repository at URL '%1$s'", - url); - } - - // If we get here either we succeeded or we ran out of alternatives. - break; - } - } - - // If any exception was handled during the URL fetch, display it now. - if (exception[0] != null) { - mFetchError = "Failed to fetch URL"; - - String reason = null; - if (exception[0] instanceof FileNotFoundException) { - // FNF has no useful getMessage, so we need to special handle it. - reason = "File not found"; - mFetchError += ": " + reason; - } else if (exception[0] instanceof SSLKeyException) { - // That's a common error and we have a pref for it. - reason = "HTTPS SSL error. You might want to force download through HTTP in the settings."; - mFetchError += ": HTTPS SSL error"; - } else if (exception[0].getMessage() != null) { - reason = - exception[0].getClass().getSimpleName().replace("Exception", "") //$NON-NLS-1$ //$NON-NLS-2$ - + ' ' - + exception[0].getMessage(); - } else { - reason = exception[0].toString(); - } - - monitor.logError("Failed to fetch URL %1$s, reason: %2$s", url, reason); - } - - if (validationError[0] != null) { - monitor.logError("%s", validationError[0]); //$NON-NLS-1$ - } - - // Stop here if we failed to validate the XML. We don't want to load it. - if (validatedDoc == null) { - return; - } - - if (usingAlternateXml) { - // We found something using the "alternate" XML schema (that is the one made up - // to support schema upgrades). That means the user can only install the tools - // and needs to upgrade them before it download more stuff. - - // Is the manager running from inside ADT? - // We check that com.android.ide.eclipse.adt.AdtPlugin exists using reflection. - - boolean isADT = false; - try { - Class adt = Class.forName("com.android.ide.eclipse.adt.AdtPlugin"); //$NON-NLS-1$ - isADT = (adt != null); - } catch (ClassNotFoundException e) { - // pass - } - - String info; - if (isADT) { - info = "This repository requires a more recent version of ADT. Please update the Eclipse Android plugin."; - mDescription = "This repository requires a more recent version of ADT, the Eclipse Android plugin.\nYou must update it before you can see other new packages."; - - } else { - info = "This repository requires a more recent version of the Tools. Please update."; - mDescription = "This repository requires a more recent version of the Tools.\nYou must update it before you can see other new packages."; - } - - mFetchError = mFetchError == null ? info : mFetchError + ". " + info; - } - - monitor.incProgress(1); - - if (xml != null) { - monitor.setDescription("Parse XML: %1$s", url); - monitor.incProgress(1); - parsePackages(validatedDoc, validatedUri, monitor); - if (mPackages == null || mPackages.length == 0) { - mDescription += "\nNo packages found."; - } else if (mPackages.length == 1) { - mDescription += "\nOne package found."; - } else { - mDescription += String.format("\n%1$d packages found.", mPackages.length); - } - } - - // done - monitor.incProgress(1); - closeStream(xml); - } - - private void setDefaultDescription() { - if (isAddonSource()) { - String desc = ""; - - if (mUiName != null) { - desc += "Add-on Provider: " + mUiName; - desc += "\n"; - } - desc += "Add-on URL: " + mUrl; - - mDescription = desc; - } else { - mDescription = String.format("SDK Source: %1$s", mUrl); - } - } - - /** - * Fetches the document at the given URL and returns it as a string. Returns - * null if anything wrong happens and write errors to the monitor. - * - * @param urlString The URL to load, as a string. - * @param monitor {@link ITaskMonitor} related to this URL. - * @param outException If non null, where to store any exception that - * happens during the fetch. - */ - private InputStream fetchXmlUrl(String urlString, - DownloadCache cache, - ITaskMonitor monitor, - Exception[] outException) { - try { - InputStream xml = cache.openCachedUrl(urlString, monitor); - if (xml != null) { - xml.mark(500000); - xml = new NonClosingInputStream(xml); - ((NonClosingInputStream) xml).setCloseBehavior(CloseBehavior.RESET); - } - return xml; - } catch (Exception e) { - if (outException != null) { - outException[0] = e; - } - } - - return null; - } - - /** - * Closes the stream, ignore any exception from InputStream.close(). - * If the stream is a NonClosingInputStream, sets it to CloseBehavior.CLOSE first. - */ - private void closeStream(InputStream is) { - if (is != null) { - if (is instanceof NonClosingInputStream) { - ((NonClosingInputStream) is).setCloseBehavior(CloseBehavior.CLOSE); - } - try { - is.close(); - } catch (IOException ignore) {} - } - } - - /** - * Validates this XML against one of the requested SDK Repository schemas. - * If the XML was correctly validated, returns the schema that worked. - * If it doesn't validate, returns null and stores the error in outError[0]. - * If we can't find a validator, returns null and set validatorFound[0] to false. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected String validateXml(InputStream xml, String url, int version, - String[] outError, Boolean[] validatorFound) { - - if (xml == null) { - return null; - } - - try { - Validator validator = getValidator(version); - - if (validator == null) { - validatorFound[0] = Boolean.FALSE; - outError[0] = String.format( - "XML verification failed for %1$s.\nNo suitable XML Schema Validator could be found in your Java environment. Please consider updating your version of Java.", - url); - return null; - } - - validatorFound[0] = Boolean.TRUE; - - // Reset the stream if it supports that operation. - assert xml.markSupported(); - xml.reset(); - - // Validation throws a bunch of possible Exceptions on failure. - validator.validate(new StreamSource(xml)); - return getSchemaUri(version); - - } catch (SAXParseException e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nLine %2$d:%3$d, Error: %4$s", - url, - e.getLineNumber(), - e.getColumnNumber(), - e.toString()); - - } catch (Exception e) { - outError[0] = String.format( - "XML verification failed for %1$s.\nError: %2$s", - url, - e.toString()); - } - return null; - } - - /** - * Manually parses the root element of the XML to extract the schema version - * at the end of the xmlns:sdk="http://schemas.android.com/sdk/android/repository/$N" - * declaration. - * - * @return 1..{@link SdkRepoConstants#NS_LATEST_VERSION} for a valid schema version - * or 0 if no schema could be found. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected int getXmlSchemaVersion(InputStream xml) { - if (xml == null) { - return 0; - } - - // Get an XML document - Document doc = null; - try { - assert xml.markSupported(); - xml.reset(); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(false); - factory.setValidating(false); - - // Parse the old document using a non namespace aware builder - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - - // We don't want the default handler which prints errors to stderr. - builder.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException e) throws SAXException { - // pass - } - @Override - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - @Override - public void error(SAXParseException e) throws SAXException { - throw e; - } - }); - - doc = builder.parse(xml); - - // Prepare a new document using a namespace aware builder - factory.setNamespaceAware(true); - builder = factory.newDocumentBuilder(); - - } catch (Exception e) { - // Failed to reset XML stream - // Failed to get builder factor - // Failed to create XML document builder - // Failed to parse XML document - // Failed to read XML document - } - - if (doc == null) { - return 0; - } - - // Check the root element is an XML with at least the following properties: - // - // - // Note that we don't have namespace support enabled, we just do it manually. - - Pattern nsPattern = Pattern.compile(getNsPattern()); - - String prefix = null; - for (Node child = doc.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE) { - prefix = null; - String name = child.getNodeName(); - int pos = name.indexOf(':'); - if (pos > 0 && pos < name.length() - 1) { - prefix = name.substring(0, pos); - name = name.substring(pos + 1); - } - if (getRootElementName().equals(name)) { - NamedNodeMap attrs = child.getAttributes(); - String xmlns = "xmlns"; //$NON-NLS-1$ - if (prefix != null) { - xmlns += ":" + prefix; //$NON-NLS-1$ - } - Node attr = attrs.getNamedItem(xmlns); - if (attr != null) { - String uri = attr.getNodeValue(); - if (uri != null) { - Matcher m = nsPattern.matcher(uri); - if (m.matches()) { - String version = m.group(1); - try { - return Integer.parseInt(version); - } catch (NumberFormatException e) { - return 0; - } - } - } - } - } - } - } - - return 0; - } - - /** - * Helper method that returns a validator for our XSD, or null if the current Java - * implementation can't process XSD schemas. - * - * @param version The version of the XML Schema. - * See {@link SdkRepoConstants#getXsdStream(int)} - */ - private Validator getValidator(int version) throws SAXException { - InputStream xsdStream = getXsdStream(version); - SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - - if (factory == null) { - return null; - } - - // This may throw a SAX Exception if the schema itself is not a valid XSD - Schema schema = factory.newSchema(new StreamSource(xsdStream)); - - Validator validator = schema == null ? null : schema.newValidator(); - - // We don't want the default handler, which by default dumps errors to stderr. - validator.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException e) throws SAXException { - // pass - } - @Override - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - @Override - public void error(SAXParseException e) throws SAXException { - throw e; - } - }); - - return validator; - } - - /** - * Parse all packages defined in the SDK Repository XML and creates - * a new mPackages array with them. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected boolean parsePackages(Document doc, String nsUri, ITaskMonitor monitor) { - - Node root = getFirstChild(doc, nsUri, getRootElementName()); - if (root != null) { - - ArrayList packages = new ArrayList(); - - // Parse license definitions - HashMap licenses = new HashMap(); - for (Node child = root.getFirstChild(); - child != null; - child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI()) && - child.getLocalName().equals(RepoConstants.NODE_LICENSE)) { - Node id = child.getAttributes().getNamedItem(RepoConstants.ATTR_ID); - if (id != null) { - licenses.put(id.getNodeValue(), child.getTextContent()); - } - } - } - - // Parse packages - for (Node child = root.getFirstChild(); - child != null; - child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI())) { - String name = child.getLocalName(); - Package p = null; - - try { - // We can load add-on and extra packages from all sources, either - // internal or user sources. - if (SdkAddonConstants.NODE_ADD_ON.equals(name)) { - p = new AddonPackage(this, child, nsUri, licenses); - - } else if (SdkAddonConstants.NODE_EXTRA.equals(name)) { - p = new ExtraPackage(this, child, nsUri, licenses); - - } else if (!isAddonSource()) { - // We only load platform, doc and tool packages from internal - // sources, never from user sources. - if (SdkRepoConstants.NODE_PLATFORM.equals(name)) { - p = new PlatformPackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_DOC.equals(name)) { - p = new DocPackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_TOOL.equals(name)) { - p = new ToolPackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_PLATFORM_TOOL.equals(name)) { - p = new PlatformToolPackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_BUILD_TOOL.equals(name)) { - p = new BuildToolPackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_SAMPLE.equals(name)) { - p = new SamplePackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_SYSTEM_IMAGE.equals(name)) { - p = new SystemImagePackage(this, child, nsUri, licenses); - } else if (SdkRepoConstants.NODE_SOURCE.equals(name)) { - p = new SourcePackage(this, child, nsUri, licenses); - } - } - - if (p != null) { - packages.add(p); - monitor.logVerbose("Found %1$s", p.getShortDescription()); - } - } catch (Exception e) { - // Ignore invalid packages - monitor.logError("Ignoring invalid %1$s element: %2$s", name, e.toString()); - } - } - } - - setPackages(packages.toArray(new Package[packages.size()])); - - return true; - } - - return false; - } - - /** - * Returns the first child element with the given XML local name. - * If xmlLocalName is null, returns the very first child element. - */ - private Node getFirstChild(Node node, String nsUri, String xmlLocalName) { - - for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - nsUri.equals(child.getNamespaceURI())) { - if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) { - return child; - } - } - } - - return null; - } - - /** - * Takes an XML document as a string as parameter and returns a DOM for it. - * - * On error, returns null and prints a (hopefully) useful message on the monitor. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected Document getDocument(InputStream xml, ITaskMonitor monitor) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setIgnoringComments(true); - factory.setNamespaceAware(true); - - DocumentBuilder builder = factory.newDocumentBuilder(); - assert xml.markSupported(); - xml.reset(); - Document doc = builder.parse(new InputSource(xml)); - - return doc; - } catch (ParserConfigurationException e) { - monitor.logError("Failed to create XML document builder"); - - } catch (SAXException e) { - monitor.logError("Failed to parse XML document"); - - } catch (IOException e) { - monitor.logError("Failed to read XML document"); - } - - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceCategory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceCategory.java deleted file mode 100644 index 263e9d5f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceCategory.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.sources; - -import com.android.sdklib.repository.IDescription; - - -/** - * The category of a given {@link SdkSource} (which represents a download site). - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public enum SdkSourceCategory implements IDescription { - - /** - * The default canonical and official Android repository. - */ - ANDROID_REPO("Android Repository", true), - - /** - * Repositories contributed by the SDK_UPDATER_URLS env var, - * only used for local debugging. - */ - GETENV_REPOS("Custom Repositories", false), - - /** - * All third-party add-ons fetched from the Android repository. - */ - ADDONS_3RD_PARTY("Third party Add-ons", true), - - /** - * All add-ons contributed locally by the user via the "Add Add-on Site" button. - */ - USER_ADDONS("User Add-ons", false), - - /** - * Add-ons contributed by the SDK_UPDATER_USER_URLS env var, - * only used for local debugging. - */ - GETENV_ADDONS("Custom Add-ons", false); - - - private final String mUiName; - private final boolean mAlwaysDisplay; - - SdkSourceCategory(String uiName, boolean alwaysDisplay) { - mUiName = uiName; - mAlwaysDisplay = alwaysDisplay; - } - - /** - * Returns the UI-visible name of the category. Displayed in the available package tree. - * Cannot be null nor empty. - */ - public String getUiName() { - return mUiName; - } - - /** - * True if this category must always be displayed by the available package tree, even - * if empty. - * When false, the category must not be displayed when empty. - */ - public boolean getAlwaysDisplay() { - return mAlwaysDisplay; - } - - @Override - public String getLongDescription() { - return getUiName(); - } - - @Override - public String getShortDescription() { - return getUiName(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceProperties.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceProperties.java deleted file mode 100644 index fb8014ce..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSourceProperties.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository.sources; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Properties; - -/** - * Properties for individual sources which are persisted by a local settings file. - *

- * All instances of {@link SdkSourceProperties} share the same singleton storage. - * The persisted setting file is loaded as necessary, however callers must persist - * it at some point by calling {@link #save()}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkSourceProperties { - - /** - * An internal file version number, in case we want to change the format later. - */ - private static final String KEY_VERSION = "@version@"; //$NON-NLS-1$ - /** - * The last known UI name of the source. - */ - public static final String KEY_NAME = "@name@"; //$NON-NLS-1$ - /** - * A non-null string if the source is disabled. Null if the source is enabled. - */ - public static final String KEY_DISABLED = "@disabled@"; //$NON-NLS-1$ - - private static final Properties sSourcesProperties = new Properties(); - private static final String SRC_FILENAME = "sites-settings.cfg"; //$NON-NLS-1$ - - private static boolean sModified = false; - - public SdkSourceProperties() { - } - - public void save() { - synchronized (sSourcesProperties) { - if (sModified && !sSourcesProperties.isEmpty()) { - saveLocked(); - sModified = false; - } - } - } - - /** - * Retrieves a property for the given source URL and the given key type. - *

- * Implementation detail: this loads the persistent settings file as needed. - * - * @param key The kind of property to retrieve for that source URL. - * @param sourceUrl The source URL. - * @param defaultValue The default value to return, if the property isn't found. Can be null. - * @return The non-null string property for the key/sourceUrl or the default value. - */ - @Nullable - public String getProperty(@NonNull String key, - @NonNull String sourceUrl, - @Nullable String defaultValue) { - String value = defaultValue; - - synchronized (sSourcesProperties) { - if (sSourcesProperties.isEmpty()) { - loadLocked(); - } - - value = sSourcesProperties.getProperty(key + sourceUrl, defaultValue); - } - - return value; - } - - /** - * Sets or remove a property for the given source URL and the given key type. - *

- * Implementation detail: this does not save the persistent settings file. - * Somehow the caller will need to call the {@link #save()} method later. - * - * @param key The kind of property to retrieve for that source URL. - * @param sourceUrl The source URL. - * @param value The new value to set (if non null) or null to remove an existing property. - */ - public void setProperty(String key, String sourceUrl, String value) { - synchronized (sSourcesProperties) { - if (sSourcesProperties.isEmpty()) { - loadLocked(); - } - - key += sourceUrl; - - String old = sSourcesProperties.getProperty(key); - if (value == null) { - if (old != null) { - sSourcesProperties.remove(key); - sModified = true; - } - } else if (old == null || !old.equals(value)) { - sSourcesProperties.setProperty(key, value); - sModified = true; - } - } - } - - /** - * Returns an internal string representation of the underlying Properties map, - * sorted by ascending keys. Useful for debugging and testing purposes only. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(" keys = Collections.list(sSourcesProperties.keys()); - Collections.sort(keys, new Comparator() { - @Override - public int compare(Object o1, Object o2) { - return o1.toString().compareTo(o2.toString()); - }}); - - for (Object key : keys) { - sb.append('\n').append(key) - .append(" = ").append(sSourcesProperties.get(key)); //$NON-NLS-1$ - } - } - sb.append('>'); - return sb.toString(); - } - - /** Load state from persistent file. Expects sSourcesProperties to be synchronized. */ - private void loadLocked() { - // Load state from persistent file - if (loadProperties()) { - // If it lacks our magic version key, don't use it - if (sSourcesProperties.getProperty(KEY_VERSION) == null) { - sSourcesProperties.clear(); - } - - sModified = false; - } - - if (sSourcesProperties.isEmpty()) { - // Nothing was loaded. Initialize the storage with a version - // identified. This isn't currently checked back, but we might - // want it later if we decide to change the way this works. - // The version key is chosen on purpose to not match any valid URL. - sSourcesProperties.setProperty(KEY_VERSION, "1"); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - /** - * Load properties from default file. Extracted so that it can be mocked in tests. - * - * @return True if actually loaded the file. False if there was an IO error or no - * file and nothing was loaded. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected boolean loadProperties() { - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SRC_FILENAME); - if (f.exists()) { - FileInputStream fis = null; - try { - fis = new FileInputStream(f); - sSourcesProperties.load(fis); - } catch (IOException ignore) { - // nop - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException ignore) {} - } - } - - return true; - } - } catch (AndroidLocationException ignore) { - // nop - } - return false; - } - - /** - * Save file to disk. Expects sSourcesProperties to be synchronized. - * Made accessible for testing purposes. - * For public usage, please use {@link #save()} instead. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void saveLocked() { - // Persist it to the file - FileOutputStream fos = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SRC_FILENAME); - - fos = new FileOutputStream(f); - - sSourcesProperties.store(fos,"## Sites Settings for Android SDK Manager");//$NON-NLS-1$ - - } catch (AndroidLocationException ignore) { - // nop - } catch (IOException ignore) { - // nop - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException ignore) {} - } - } - } - - /** Empty current property list. Made accessible for testing purposes. */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void clear() { - synchronized (sSourcesProperties) { - sSourcesProperties.clear(); - sModified = false; - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSources.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSources.java deleted file mode 100644 index 7c663cad..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSources.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.sources; - -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.repository.SdkSysImgConstants; -import com.android.utils.ILogger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.Iterator; -import java.util.Properties; -import java.util.Map.Entry; - -/** - * A list of sdk-repository and sdk-addon sources, sorted by {@link SdkSourceCategory}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkSources { - - private static final String KEY_COUNT = "count"; - - private static final String KEY_SRC = "src"; - - private static final String SRC_FILENAME = "repositories.cfg"; //$NON-NLS-1$ - - private final EnumMap> mSources = - new EnumMap>(SdkSourceCategory.class); - - private ArrayList mChangeListeners; // lazily initialized - - - public SdkSources() { - } - - /** - * Adds a new source to the Sources list. - *

- * Implementation detail: {@link SdkSources} doesn't invoke {@link #notifyChangeListeners()} - * directly. Callers who use {@code add()} are responsible for notifying the listeners once - * they are done modifying the sources list. The intent is to notify the listeners only once - * at the end, not for every single addition. - */ - public void add(SdkSourceCategory category, SdkSource source) { - synchronized (mSources) { - ArrayList list = mSources.get(category); - if (list == null) { - list = new ArrayList(); - mSources.put(category, list); - } - - list.add(source); - } - } - - /** - * Removes a source from the Sources list. - *

- * Callers who remove entries are responsible for notifying the listeners using - * {@link #notifyChangeListeners()} once they are done modifying the sources list. - */ - public void remove(SdkSource source) { - synchronized (mSources) { - Iterator>> it = - mSources.entrySet().iterator(); - while (it.hasNext()) { - Entry> entry = it.next(); - ArrayList list = entry.getValue(); - - if (list.remove(source)) { - if (list.isEmpty()) { - // remove the entry since the source list became empty - it.remove(); - } - } - } - } - } - - /** - * Removes all the sources in the given category. - *

- * Callers who remove entries are responsible for notifying the listeners using - * {@link #notifyChangeListeners()} once they are done modifying the sources list. - */ - public void removeAll(SdkSourceCategory category) { - synchronized (mSources) { - mSources.remove(category); - } - } - - /** - * Returns a set of all categories that must be displayed. This includes all - * categories that are to be always displayed as well as all categories which - * have at least one source. - * Might return a empty array, but never returns null. - */ - public SdkSourceCategory[] getCategories() { - ArrayList cats = new ArrayList(); - - for (SdkSourceCategory cat : SdkSourceCategory.values()) { - if (cat.getAlwaysDisplay()) { - cats.add(cat); - } else { - synchronized (mSources) { - ArrayList list = mSources.get(cat); - if (list != null && !list.isEmpty()) { - cats.add(cat); - } - } - } - } - - return cats.toArray(new SdkSourceCategory[cats.size()]); - } - - /** - * Returns a new array of sources attached to the given category. - * Might return an empty array, but never returns null. - */ - public SdkSource[] getSources(SdkSourceCategory category) { - synchronized (mSources) { - ArrayList list = mSources.get(category); - if (list == null) { - return new SdkSource[0]; - } else { - return list.toArray(new SdkSource[list.size()]); - } - } - } - - /** - * Returns true if there are sources for the given category. - */ - public boolean hasSources(SdkSourceCategory category) { - synchronized (mSources) { - ArrayList list = mSources.get(category); - return list != null && !list.isEmpty(); - } - } - - /** - * Returns an array of the sources across all categories. This is never null. - */ - public SdkSource[] getAllSources() { - synchronized (mSources) { - int n = 0; - - for (ArrayList list : mSources.values()) { - n += list.size(); - } - - SdkSource[] sources = new SdkSource[n]; - - int i = 0; - for (ArrayList list : mSources.values()) { - for (SdkSource source : list) { - sources[i++] = source; - } - } - - return sources; - } - } - - /** - * Each source keeps a local cache of whatever it loaded recently. - * This calls {@link SdkSource#clearPackages()} on all the available sources, - * and the next call to {@link SdkSource#getPackages()} will actually reload - * the remote package list. - */ - public void clearAllPackages() { - synchronized (mSources) { - for (ArrayList list : mSources.values()) { - for (SdkSource source : list) { - source.clearPackages(); - } - } - } - } - - /** - * Returns the category of a given source, or null if the source is unknown. - *

- * Note that this method uses object identity to find a given source, and does - * not identify sources by their URL like {@link #hasSourceUrl(SdkSource)} does. - *

- * The search is O(N), which should be acceptable on the expectedly small source list. - */ - public SdkSourceCategory getCategory(SdkSource source) { - if (source != null) { - synchronized (mSources) { - for (Entry> entry : mSources.entrySet()) { - if (entry.getValue().contains(source)) { - return entry.getKey(); - } - } - } - } - return null; - } - - /** - * Returns true if there's already a similar source in the sources list - * under any category. - *

- * Important: The match is NOT done on object identity. - * Instead, this searches for a similar source, based on - * {@link SdkSource#equals(Object)} which compares the source URLs. - *

- * The search is O(N), which should be acceptable on the expectedly small source list. - */ - public boolean hasSourceUrl(SdkSource source) { - synchronized (mSources) { - for (ArrayList list : mSources.values()) { - for (SdkSource s : list) { - if (s.equals(source)) { - return true; - } - } - } - return false; - } - } - - /** - * Returns true if there's already a similar source in the sources list - * under the specified category. - *

- * Important: The match is NOT done on object identity. - * Instead, this searches for a similar source, based on - * {@link SdkSource#equals(Object)} which compares the source URLs. - *

- * The search is O(N), which should be acceptable on the expectedly small source list. - */ - public boolean hasSourceUrl(SdkSourceCategory category, SdkSource source) { - synchronized (mSources) { - ArrayList list = mSources.get(category); - if (list != null) { - for (SdkSource s : list) { - if (s.equals(source)) { - return true; - } - } - } - return false; - } - } - - /** - * Loads all user sources. This replaces all existing user sources - * by the ones from the property file. - *

- * This calls {@link #notifyChangeListeners()} at the end of the operation. - */ - public void loadUserAddons(ILogger log) { - // Implementation detail: synchronize on the sources list to make sure that - // a- the source list doesn't change while we load/save it, and most important - // b- to make sure it's not being saved while loaded or the reverse. - // In most cases we do these operation from the UI thread so it's not really - // that necessary. This is more a protection in case of someone calls this - // from a worker thread by mistake. - synchronized (mSources) { - // Remove all existing user sources - removeAll(SdkSourceCategory.USER_ADDONS); - - // Load new user sources from property file - FileInputStream fis = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SRC_FILENAME); - if (f.exists()) { - fis = new FileInputStream(f); - - Properties props = new Properties(); - props.load(fis); - - int count = Integer.parseInt(props.getProperty(KEY_COUNT, "0")); - - for (int i = 0; i < count; i++) { - String url = props.getProperty(String.format("%s%02d", KEY_SRC, i)); //$NON-NLS-1$ - if (url != null) { - // FIXME: this code originally only dealt with add-on XML sources. - // Now we'd like it to deal with system-image sources too, but we - // don't know which kind of object it is (at least not without - // trying to fetch it.) As a temporary workaround, just take a - // guess based on the leaf URI name. However ideally what we can - // simply do is add a checkbox "is system-image XML" in the user - // dialog and pass this info down here. Another alternative is to - // make a "dynamic" source object that tries to guess its type once - // the URI has been fetched. - SdkSource s; - if (url.endsWith(SdkSysImgConstants.URL_DEFAULT_FILENAME)) { - s = new SdkSysImgSource(url, null/*uiName*/); - } else { - s = new SdkAddonSource(url, null/*uiName*/); - } - if (!hasSourceUrl(s)) { - add(SdkSourceCategory.USER_ADDONS, s); - } - } - } - } - - } catch (NumberFormatException e) { - log.error(e, null); - - } catch (AndroidLocationException e) { - log.error(e, null); - - } catch (IOException e) { - log.error(e, null); - - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - } - } - } - } - notifyChangeListeners(); - } - - /** - * Saves all the user sources. - * @param log Logger. Cannot be null. - */ - public void saveUserAddons(ILogger log) { - // See the implementation detail note in loadUserAddons() about the synchronization. - synchronized (mSources) { - FileOutputStream fos = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SRC_FILENAME); - - fos = new FileOutputStream(f); - - Properties props = new Properties(); - - int count = 0; - for (SdkSource s : getSources(SdkSourceCategory.USER_ADDONS)) { - props.setProperty(String.format("%s%02d", KEY_SRC, count), //$NON-NLS-1$ - s.getUrl()); - count++; - } - props.setProperty(KEY_COUNT, Integer.toString(count)); - - props.store( fos, "## User Sources for Android SDK Manager"); //$NON-NLS-1$ - - } catch (AndroidLocationException e) { - log.error(e, null); - - } catch (IOException e) { - log.error(e, null); - - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - } - } - } - } - } - - /** - * Adds a listener that will be notified when the sources list has changed. - * - * @param changeListener A non-null listener to add. Ignored if already present. - * @see SdkSources#notifyChangeListeners() - */ - public void addChangeListener(Runnable changeListener) { - assert changeListener != null; - if (mChangeListeners == null) { - mChangeListeners = new ArrayList(); - } - synchronized (mChangeListeners) { - if (changeListener != null && !mChangeListeners.contains(changeListener)) { - mChangeListeners.add(changeListener); - } - } - } - - /** - * Removes a listener from the list of listeners to notify when the sources change. - * - * @param changeListener A listener to remove. Ignored if not previously added. - */ - public void removeChangeListener(Runnable changeListener) { - if (mChangeListeners != null && changeListener != null) { - synchronized (mChangeListeners) { - mChangeListeners.remove(changeListener); - } - } - } - - /** - * Invoke all the registered change listeners, if any. - *

- * This may be called from a worker thread, in which case the runnable - * should take care of only updating UI from a main thread. - */ - public void notifyChangeListeners() { - if (mChangeListeners == null) { - return; - } - synchronized (mChangeListeners) { - for (Runnable runnable : mChangeListeners) { - try { - runnable.run(); - } catch (Throwable ignore) { - assert ignore == null : - "A SdkSource.ChangeListener failed with an exception: " + ignore.toString(); - } - } - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSysImgSource.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSysImgSource.java deleted file mode 100644 index 1c90b4cd..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/sources/SdkSysImgSource.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.repository.sources; - -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.repository.SdkSysImgConstants; - -import org.w3c.dom.Document; - -import java.io.InputStream; - - -/** - * An sdk-sys-img source, i.e. a download site for system-image packages. - * A repository describes one or more {@link Package}s available for download. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkSysImgSource extends SdkSource { - - /** - * Constructs a new source for the given repository URL. - * @param url The source URL. Cannot be null. If the URL ends with a /, the default - * sys-img.xml filename will be appended automatically. - * @param uiName The UI-visible name of the source. Can be null. - */ - public SdkSysImgSource(String url, String uiName) { - super(url, uiName); - } - - /** - * Returns true if this is an addon source. - * We only load addons and extras from these sources. - */ - @Override - public boolean isAddonSource() { - return false; - } - - /** - * Returns true if this is a system-image source. - * We only load system-images from these sources. - */ - @Override - public boolean isSysImgSource() { - return true; - } - - - @Override - protected String[] getDefaultXmlFileUrls() { - return new String[] { SdkSysImgConstants.URL_DEFAULT_FILENAME }; - } - - @Override - protected int getNsLatestVersion() { - return SdkSysImgConstants.NS_LATEST_VERSION; - } - - @Override - protected String getNsUri() { - return SdkSysImgConstants.NS_URI; - } - - @Override - protected String getNsPattern() { - return SdkSysImgConstants.NS_PATTERN; - } - - @Override - protected String getSchemaUri(int version) { - return SdkSysImgConstants.getSchemaUri(version); - } - - @Override - protected String getRootElementName() { - return SdkSysImgConstants.NODE_SDK_SYS_IMG; - } - - @Override - protected InputStream getXsdStream(int version) { - return SdkSysImgConstants.getXsdStream(version); - } - - /** - * This kind of schema does not support forward-evolution of the <tool> element. - * - * @param xml The input XML stream. Can be null. - * @return Always null. - * @null This implementation always return null. - */ - @Override - protected Document findAlternateToolsXml(@Nullable InputStream xml) { - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ArchiveInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ArchiveInfo.java deleted file mode 100644 index c2098389..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ArchiveInfo.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.updater; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveReplacement; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Represents an archive that we want to install. - * Note that the installer deals with archives whereas the user mostly sees packages - * but as far as we are concerned for installation there's a 1-to-1 mapping. - *

- * A new archive is always a remote archive that needs to be downloaded and then - * installed. It can replace an existing local one. It can also depends on another - * (new or local) archive, which means the dependent archive needs to be successfully - * installed first. Finally this archive can also be a dependency for another one. - *

- * The accepted and rejected flags are used by {@code SdkUpdaterChooserDialog} to follow - * user choices. The installer should never install something that is not accepted. - *

- * Note: There is currently no logic to support more than one level of - * dependency, either here or in the {@code SdkUpdaterChooserDialog}, since we currently - * have no need for it. - * - * @see ArchiveInfo#ArchiveInfo(Archive, Archive, ArchiveInfo[]) - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class ArchiveInfo extends ArchiveReplacement implements Comparable { - - private final ArchiveInfo[] mDependsOn; - private final ArrayList mDependencyFor = new ArrayList(); - private boolean mAccepted; - private boolean mRejected; - - /** - * Creates a new replacement where the {@code newArchive} will replace the - * currently installed {@code replaced} archive. - * When {@code newArchive} is not intended to replace anything (e.g. because - * the user is installing a new package not present on her system yet), then - * {@code replace} shall be null. - * - * @param newArchive A "new archive" to be installed. This is always an archive - * that comes from a remote site. This may be null. - * @param replaced An optional local archive that the new one will replace. - * Can be null if this archive does not replace anything. - * @param dependsOn An optional new or local dependency, that is an archive that - * this archive depends upon. In other words, we can only install - * this archive if the dependency has been successfully installed. It also - * means we need to install the dependency first. Can be null or empty. - * However it cannot contain nulls. - */ - public ArchiveInfo( - @Nullable Archive newArchive, - @Nullable Archive replaced, - @Nullable ArchiveInfo[] dependsOn) { - super(newArchive, replaced); - mDependsOn = dependsOn; - } - - /** - * Returns an optional new or local dependency, that is an archive that this - * archive depends upon. In other words, we can only install this archive if the - * dependency has been successfully installed. It also means we need to install the - * dependency first. - *

- * This array can be null or empty. It can't contain nulls though. - */ - @Nullable - public ArchiveInfo[] getDependsOn() { - return mDependsOn; - } - - /** - * Returns true if this new archive is a dependency for another one that we - * want to install. - */ - public boolean isDependencyFor() { - return !mDependencyFor.isEmpty(); - } - - /** - * Adds an {@link ArchiveInfo} for which this package is a dependency. - * This means the package added here depends on this package. - */ - @NonNull - public ArchiveInfo addDependencyFor(ArchiveInfo dependencyFor) { - if (!mDependencyFor.contains(dependencyFor)) { - mDependencyFor.add(dependencyFor); - } - - return this; - } - - /** - * Returns the list of {@link ArchiveInfo} for which this package is a dependency. - * This means the packages listed here depend on this package. - *

- * Implementation detail: this is the internal mutable list. Callers should not modify it. - * This list can be empty but is never null. - */ - @NonNull - public Collection getDependenciesFor() { - return mDependencyFor; - } - - /** - * Sets whether this archive was accepted (either manually by the user or - * automatically if it doesn't have a license) for installation. - */ - public void setAccepted(boolean accepted) { - mAccepted = accepted; - } - - /** - * Returns whether this archive was accepted (either manually by the user or - * automatically if it doesn't have a license) for installation. - */ - public boolean isAccepted() { - return mAccepted; - } - - /** - * Sets whether this archive was rejected manually by the user. - * An archive can neither accepted nor rejected. - */ - public void setRejected(boolean rejected) { - mRejected = rejected; - } - - /** - * Returns whether this archive was rejected manually by the user. - * An archive can neither accepted nor rejected. - */ - public boolean isRejected() { - return mRejected; - } - - /** - * ArchiveInfos are compared using ther "new archive" ordering. - * - * @see Archive#compareTo(Archive) - */ - @Override - public int compareTo(ArchiveInfo rhs) { - if (getNewArchive() != null && rhs != null) { - return getNewArchive().compareTo(rhs.getNewArchive()); - } - return 0; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ISettingsPage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ISettingsPage.java deleted file mode 100644 index 1da1b01c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/ISettingsPage.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.updater; - -import com.android.sdklib.internal.repository.DownloadCache; - -import java.net.URL; -import java.util.Properties; - -/** - * Interface that a settings page must implement. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface ISettingsPage { - - /** - * Java system setting picked up by {@link URL} for http proxy port. - * Type: String. - */ - String KEY_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - - /** - * Java system setting picked up by {@link URL} for http proxy host. - * Type: String. - */ - String KEY_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - - /** - * Setting to force using http:// instead of https:// connections. - * Type: Boolean. - * Default: False. - */ - String KEY_FORCE_HTTP = "sdkman.force.http"; //$NON-NLS-1$ - - /** - * Setting to display only packages that are new or updates. - * Type: Boolean. - * Default: True. - */ - String KEY_SHOW_UPDATE_ONLY = "sdkman.show.update.only"; //$NON-NLS-1$ - - /** - * Setting to ask for permission before restarting ADB. - * Type: Boolean. - * Default: False. - */ - String KEY_ASK_ADB_RESTART = "sdkman.ask.adb.restart"; //$NON-NLS-1$ - - /** - * Setting to use the {@link DownloadCache}, for small manifest XML files. - * Type: Boolean. - * Default: True. - */ - String KEY_USE_DOWNLOAD_CACHE = "sdkman.use.dl.cache"; //$NON-NLS-1$ - - /** - * Setting to enabling previews in the package list - * Type: Boolean. - * Default: True. - */ - String KEY_ENABLE_PREVIEWS = "sdkman.enable.previews2"; //$NON-NLS-1$ - - /** - * Setting to set the density of the monitor. - * Type: Integer. - * Default: -1 - */ - String KEY_MONITOR_DENSITY = "sdkman.monitor.density"; //$NON-NLS-1$ - - /** Loads settings from the given {@link Properties} container and update the page UI. */ - void loadSettings(Properties inSettings); - - /** Called by the application to retrieve settings from the UI and store them in - * the given {@link Properties} container. */ - void retrieveSettings(Properties outSettings); - - /** - * Called by the application to give a callback that the page should invoke when - * settings have changed. - */ - void setOnSettingsChanged(SettingsChangedCallback settingsChangedCallback); - - /** - * Callback used to notify the application that settings have changed and need to be - * applied. - */ - interface SettingsChangedCallback { - /** - * Invoked by the settings page when settings have changed and need to be - * applied. The application will call {@link ISettingsPage#retrieveSettings(Properties)} - * and apply the new settings. - */ - void onSettingsChanged(ISettingsPage page); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/IUpdaterData.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/IUpdaterData.java deleted file mode 100644 index b3a74f2f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/IUpdaterData.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.updater; - -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.utils.ILogger; - - -/** - * Interface used to retrieve some parameters from an {@link UpdaterData} instance. - * Useful mostly for unit tests purposes. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface IUpdaterData { - - ITaskFactory getTaskFactory(); - - ILogger getSdkLog(); - - DownloadCache getDownloadCache(); - - SdkManager getSdkManager(); - - AvdManager getAvdManager(); - - SettingsController getSettingsController(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PackageLoader.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PackageLoader.java deleted file mode 100644 index c0314d4b..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PackageLoader.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.updater; - -import com.android.annotations.NonNull; -import com.android.sdklib.internal.repository.AddonsListFetcher; -import com.android.sdklib.internal.repository.AddonsListFetcher.Site; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.sources.SdkAddonSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.internal.repository.sources.SdkSysImgSource; -import com.android.sdklib.repository.SdkAddonsListConstants; -import com.android.sdklib.repository.SdkRepoConstants; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Loads packages fetched from the remote SDK Repository and keeps track - * of their state compared with the current local SDK installation. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class PackageLoader { - - /** The update data context. Never null. */ - private final UpdaterData mUpdaterData; - - /** - * The {@link DownloadCache} override. Can be null, in which case the one from - * {@link UpdaterData} is used instead. - * @see #getDownloadCache() - */ - private final DownloadCache mOverrideCache; - - /** - * 0 = need to fetch remote addons list once.. - * 1 = fetch succeeded, don't need to do it any more. - * -1= fetch failed, do it again only if the user requests a refresh - * or changes the force-http setting. - */ - private int mStateFetchRemoteAddonsList; - - - /** - * Interface for the callback called by - * {@link PackageLoader#loadPackages(boolean, ISourceLoadedCallback)}. - *

- * After processing each source, the package loader calls {@link #onUpdateSource} - * with the list of packages found in that source. - * By returning true from {@link #onUpdateSource}, the client tells the loader to - * continue and process the next source. By returning false, it tells to stop loading. - *

- * The {@link #onLoadCompleted()} method is guaranteed to be called at the end, no - * matter how the loader stopped, so that the client can clean up or perform any - * final action. - */ - public interface ISourceLoadedCallback { - /** - * After processing each source, the package loader calls this method with the - * list of packages found in that source. - * By returning true from {@link #onUpdateSource}, the client tells - * the loader to continue and process the next source. - * By returning false, it tells to stop loading. - *

- * Important: This method is called from a sub-thread, so clients which - * try to access any UI widgets must wrap their calls into - * {@code Display.syncExec(Runnable)} or {@code Display.asyncExec(Runnable)}. - * - * @param packages All the packages loaded from the source. Never null. - * @return True if the load operation should continue, false if it should stop. - */ - boolean onUpdateSource(SdkSource source, Package[] packages); - - /** - * This method is guaranteed to be called at the end, no matter how the - * loader stopped, so that the client can clean up or perform any final action. - */ - void onLoadCompleted(); - } - - /** - * Interface describing the task of installing a specific package. - * For details on the operation, - * see {@link PackageLoader#loadPackagesWithInstallTask(int, IAutoInstallTask)}. - * - * @see PackageLoader#loadPackagesWithInstallTask(int, IAutoInstallTask) - */ - public interface IAutoInstallTask { - /** - * Invoked by the loader once a source has been loaded and its package - * definitions are known. The method should return the {@code packages} - * array and can modify it if necessary. - * The loader will call {@link #acceptPackage(Package)} on all the packages returned. - * - * @param source The source of the packages. Null for the locally installed packages. - * @param packages The packages found in the source. - */ - Package[] filterLoadedSource(SdkSource source, Package[] packages); - - /** - * Called by the install task for every package available (new ones, updates as well - * as existing ones that don't have a potential update.) - * The method should return true if this is a package that should be installed. - *

- * Important: This method is called from a sub-thread, so clients who try - * to access any UI widgets must wrap their calls into {@code Display.syncExec(Runnable)} - * or {@code Display.asyncExec(Runnable)}. - */ - boolean acceptPackage(Package pkg); - - /** - * Called when the accepted package has been installed, successfully or not. - * If an already installed (aka existing) package has been accepted, this will - * be called with a 'true' success and the actual install paths. - *

- * Important: This method is called from a sub-thread, so clients who try - * to access any UI widgets must wrap their calls into {@code Display.syncExec(Runnable)} - * or {@code Display.asyncExec(Runnable)}. - */ - void setResult(boolean success, Map installPaths); - - /** - * Called when the task is done iterating and completed. - */ - void taskCompleted(); - } - - /** - * Creates a new PackageManager associated with the given {@link UpdaterData} - * and using the {@link UpdaterData}'s default {@link DownloadCache}. - * - * @param updaterData The {@link UpdaterData}. Must not be null. - */ - public PackageLoader(UpdaterData updaterData) { - mUpdaterData = updaterData; - mOverrideCache = null; - } - - /** - * Creates a new PackageManager associated with the given {@link UpdaterData} - * but using the specified {@link DownloadCache} instead of the one from - * {@link UpdaterData}. - * - * @param updaterData The {@link UpdaterData}. Must not be null. - * @param cache The {@link DownloadCache} to use instead of the one from {@link UpdaterData}. - */ - public PackageLoader(UpdaterData updaterData, DownloadCache cache) { - mUpdaterData = updaterData; - mOverrideCache = cache; - } - - public UpdaterData getUpdaterData() { - return mUpdaterData; - } - - /** - * Runs a runnable on the UI thread. - * The base implementation just runs the runnable right away. - * - * @param r Non-null runnable. - */ - protected void runOnUiThread(@NonNull Runnable r) { - r.run(); - } - - /** - * Loads all packages from the remote repository. - * This runs in an {@link ITask}. The call is blocking. - *

- * The callback is called with each set of {@link PkgItem} found in each source. - * The caller is responsible to accumulate the packages given to the callback - * after each source is finished loaded. In return the callback tells the loader - * whether to continue loading sources. - *

- * Normally this method doesn't access the remote source if it's already - * been loaded in the in-memory source (e.g. don't fetch twice). - * - * @param overrideExisting Set this to true when the caller wants to - * check for updates and discard any existing source already - * loaded in memory. It should be false for normal use. - * @param sourceLoadedCallback The callback to invoke for each loaded source. - */ - public void loadPackages( - final boolean overrideExisting, - final ISourceLoadedCallback sourceLoadedCallback) { - try { - if (mUpdaterData == null) { - return; - } - - mUpdaterData.getTaskFactory().start("Loading Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - monitor.setProgressMax(10); - - // get local packages and offer them to the callback - Package[] localPkgs = - mUpdaterData.getInstalledPackages(monitor.createSubMonitor(1)); - if (localPkgs == null) { - localPkgs = new Package[0]; - } - if (!sourceLoadedCallback.onUpdateSource(null, localPkgs)) { - return; - } - - // get remote packages - boolean forceHttp = - mUpdaterData.getSettingsController().getSettings().getForceHttp(); - loadRemoteAddonsList(monitor.createSubMonitor(1)); - - SdkSource[] sources = mUpdaterData.getSources().getAllSources(); - try { - if (sources != null && sources.length > 0) { - ITaskMonitor subMonitor = monitor.createSubMonitor(8); - subMonitor.setProgressMax(sources.length); - for (SdkSource source : sources) { - Package[] pkgs = source.getPackages(); - if (pkgs == null || overrideExisting) { - source.load(getDownloadCache(), - subMonitor.createSubMonitor(1), - forceHttp); - pkgs = source.getPackages(); - } - if (pkgs == null) { - continue; - } - - // Notify the callback a new source has finished loading. - // If the callback requests so, stop right away. - if (!sourceLoadedCallback.onUpdateSource(source, pkgs)) { - return; - } - } - } - } catch(Exception e) { - monitor.logError("Loading source failed: %1$s", e.toString()); - } finally { - monitor.setDescription("Done loading packages."); - } - } - }); - } finally { - sourceLoadedCallback.onLoadCompleted(); - } - } - - /** - * Load packages, source by source using - * {@link #loadPackages(boolean, ISourceLoadedCallback)}, - * and executes the given {@link IAutoInstallTask} on the current package list. - * That is for each package known, the install task is queried to find if - * the package is the one to be installed or updated. - *

- * - If an already installed package is accepted by the task, it is returned.
- * - If a new package (remotely available but not installed locally) is accepted, - * the user will be prompted for permission to install it.
- * - If an existing package has updates, the install task will be accept if it - * accepts one of the updating packages, and if yes the the user will be - * prompted for permission to install it.
- *

- * Only one package can be accepted, after which the task is completed. - * There is no direct return value, {@link IAutoInstallTask#setResult} is called on the - * result of the accepted package. - * When the task is completed, {@link IAutoInstallTask#taskCompleted()} is called. - *

- * The call is blocking. Although the name says "Task", this is not an {@link ITask} - * running in its own thread but merely a synchronous call. - * - * @param installFlags Flags for installation such as - * {@link UpdaterData#TOOLS_MSG_UPDATED_FROM_ADT}. - * @param installTask The task to perform. - */ - public void loadPackagesWithInstallTask( - final int installFlags, - final IAutoInstallTask installTask) { - - loadPackages(false /*overrideExisting*/, new ISourceLoadedCallback() { - List mArchivesToInstall = new ArrayList(); - Map mInstallPaths = new HashMap(); - - @Override - public boolean onUpdateSource(SdkSource source, Package[] packages) { - packages = installTask.filterLoadedSource(source, packages); - if (packages == null || packages.length == 0) { - // Tell loadPackages() to process the next source. - return true; - } - - for (Package pkg : packages) { - if (pkg.isLocal()) { - // This is a local (aka installed) package - if (installTask.acceptPackage(pkg)) { - // If the caller is accepting an installed package, - // return a success and give the package's install path - Archive[] a = pkg.getArchives(); - // an installed package should have one local compatible archive - if (a.length == 1 && a[0].isCompatible()) { - mInstallPaths.put(pkg, new File(a[0].getLocalOsPath())); - } - } - - } else { - // This is a remote package - if (installTask.acceptPackage(pkg)) { - // The caller is accepting this remote package. We'll install it. - for (Archive archive : pkg.getArchives()) { - if (archive.isCompatible()) { - mArchivesToInstall.add(archive); - break; - } - } - } - } - } - - // Tell loadPackages() to process the next source. - return true; - } - - @Override - public void onLoadCompleted() { - if (!mArchivesToInstall.isEmpty()) { - installArchives(mArchivesToInstall); - } - if (mInstallPaths == null) { - installTask.setResult(false, null); - } else { - installTask.setResult(true, mInstallPaths); - } - - installTask.taskCompleted(); - } - - /** - * Shows the UI of the install selector. - * If the package is then actually installed, refresh the local list and - * notify the install task of the installation path. - * - * @param archivesToInstall The archives to install. - */ - private void installArchives(final List archivesToInstall) { - // Actually install the new archives that we just found. - // This will display some UI so we need a shell's sync exec. - - final List installedArchives = new ArrayList(); - - runOnUiThread(new Runnable() { - @Override - public void run() { - List archives = - mUpdaterData.updateOrInstallAll_WithGUI( - archivesToInstall, - true /* includeObsoletes */, - installFlags); - - if (archives != null) { - installedArchives.addAll(archives); - } - } - }); - - if (installedArchives.isEmpty()) { - // We failed to install anything. - mInstallPaths = null; - return; - } - - // The local package list has changed, make sure to refresh it - mUpdaterData.getSdkManager().reloadSdk(mUpdaterData.getSdkLog()); - mUpdaterData.getLocalSdkParser().clearPackages(); - final Package[] localPkgs = mUpdaterData.getInstalledPackages( - new NullTaskMonitor(mUpdaterData.getSdkLog())); - - // Scan the installed package list to find the install paths. - for (Archive installedArchive : installedArchives) { - Package pkg = installedArchive.getParentPackage(); - - for (Package localPkg : localPkgs) { - if (localPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - Archive[] localArchive = localPkg.getArchives(); - if (localArchive.length == 1 && localArchive[0].isCompatible()) { - mInstallPaths.put( - localPkg, - new File(localArchive[0].getLocalOsPath())); - } - } - } - } - } - }); - } - - - /** - * Loads the remote add-ons list. - */ - public void loadRemoteAddonsList(ITaskMonitor monitor) { - - if (mStateFetchRemoteAddonsList != 0) { - return; - } - - mUpdaterData.getTaskFactory().start("Load Add-ons List", monitor, new ITask() { - @Override - public void run(ITaskMonitor subMonitor) { - loadRemoteAddonsListInTask(subMonitor); - } - }); - } - - private void loadRemoteAddonsListInTask(ITaskMonitor monitor) { - mStateFetchRemoteAddonsList = -1; - - String url = SdkAddonsListConstants.URL_ADDON_LIST; - - // We override SdkRepoConstants.URL_GOOGLE_SDK_SITE if this is defined - String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (baseUrl != null) { - if (!baseUrl.isEmpty() && baseUrl.endsWith("/")) { //$NON-NLS-1$ - if (url.startsWith(SdkRepoConstants.URL_GOOGLE_SDK_SITE)) { - url = baseUrl + url.substring(SdkRepoConstants.URL_GOOGLE_SDK_SITE.length()); - } - } else { - monitor.logError("Ignoring invalid SDK_TEST_BASE_URL: %1$s", baseUrl); //$NON-NLS-1$ - } - } - - if (mUpdaterData.getSettingsController().getSettings().getForceHttp()) { - url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Hook to bypass loading 3rd party addons lists. - boolean fetch3rdParties = System.getenv("SDK_SKIP_3RD_PARTIES") == null; - - AddonsListFetcher fetcher = new AddonsListFetcher(); - Site[] sites = fetcher.fetch(url, getDownloadCache(), monitor); - if (sites != null) { - SdkSources sources = mUpdaterData.getSources(); - sources.removeAll(SdkSourceCategory.ADDONS_3RD_PARTY); - - if (fetch3rdParties) { - for (Site s : sites) { - switch (s.getType()) { - case ADDON_SITE: - sources.add(SdkSourceCategory.ADDONS_3RD_PARTY, - new SdkAddonSource(s.getUrl(), s.getUiName())); - break; - case SYS_IMG_SITE: - sources.add(SdkSourceCategory.ADDONS_3RD_PARTY, - new SdkSysImgSource(s.getUrl(), s.getUiName())); - break; - } - } - } - - sources.notifyChangeListeners(); - - mStateFetchRemoteAddonsList = 1; - } - - monitor.setDescription("Fetched Add-ons List successfully"); - } - - /** - * Returns the {@link DownloadCache} to use. - * - * @return Returns {@link #mOverrideCache} if not null; otherwise returns the - * one from {@link UpdaterData} is used instead. - */ - private DownloadCache getDownloadCache() { - return mOverrideCache != null ? mOverrideCache : mUpdaterData.getDownloadCache(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PkgItem.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PkgItem.java deleted file mode 100644 index 60f7aa04..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/PkgItem.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2011 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.internal.repository.updater; - -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.FullRevision; - -/** - * A {@link PkgItem} represents one main {@link Package} combined with its state - * and an optional update package. - *

- * The main package is final and cannot change since it's what "defines" this PkgItem. - * The state or update package can change later. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class PkgItem implements Comparable { - private final PkgState mState; - private final Package mMainPkg; - private Package mUpdatePkg; - private boolean mChecked; - - /** - * The state of the a given {@link PkgItem}, that is the relationship between - * a given remote package and the local repository. - */ - public enum PkgState { - // Implementation detail: if this is changed then PackageDiffLogic#STATES - // and PackageDiffLogic#processSource() need to be changed accordingly. - - /** - * Package is locally installed and may or may not have an update. - */ - INSTALLED, - - /** - * There's a new package available on the remote site that isn't installed locally. - */ - NEW - } - - /** - * Create a new {@link PkgItem} for this main package. - * The main package is final and cannot change since it's what "defines" this PkgItem. - * The state or update package can change later. - */ - public PkgItem(Package mainPkg, PkgState state) { - mMainPkg = mainPkg; - mState = state; - assert mMainPkg != null; - } - - public boolean isObsolete() { - return mMainPkg.isObsolete(); - } - - public boolean isChecked() { - return mChecked; - } - - public void setChecked(boolean checked) { - mChecked = checked; - } - - public Package getUpdatePkg() { - return mUpdatePkg; - } - - public boolean hasUpdatePkg() { - return mUpdatePkg != null; - } - - public String getName() { - return mMainPkg.getListDescription(); - } - - public FullRevision getRevision() { - return mMainPkg.getRevision(); - } - - /** - * @deprecated Use {@link #getMainPackage()} with the {@link IDescription} interface instead. - */ - @Deprecated - public String getDescription() { - return mMainPkg.getLongDescription(); - } - - public Package getMainPackage() { - return mMainPkg; - } - - public PkgState getState() { - return mState; - } - - public SdkSource getSource() { - return mMainPkg.getParentSource(); - } - - @Nullable - public AndroidVersion getAndroidVersion() { - return mMainPkg instanceof IAndroidVersionProvider ? - ((IAndroidVersionProvider) mMainPkg).getAndroidVersion() : - null; - } - - public Archive[] getArchives() { - return mMainPkg.getArchives(); - } - - @Override - public int compareTo(PkgItem pkg) { - return getMainPackage().compareTo(pkg.getMainPackage()); - } - - /** - * Returns true if this package or its updating packages contains - * the exact given archive. - * Important: This compares object references, not object equality. - */ - public boolean hasArchive(Archive archive) { - if (mMainPkg.hasArchive(archive)) { - return true; - } - if (mUpdatePkg != null && mUpdatePkg.hasArchive(archive)) { - return true; - } - return false; - } - - /** - * Returns true if the main package has at least one archive - * compatible with the current platform. - */ - public boolean hasCompatibleArchive() { - return mMainPkg.hasCompatibleArchive(); - } - - /** - * Checks whether the main packages are of the same type and are - * not an update of each other and have the same revision number. - */ - public boolean isSameMainPackageAs(Package pkg) { - if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - // package revision numbers must match - return mMainPkg.getRevision().equals(pkg.getRevision()); - } - return false; - } - - /** - * Checks whether the update packages are of the same type and are - * not an update of each other and have the same revision numbers. - */ - public boolean isSameUpdatePackageAs(Package pkg) { - if (mUpdatePkg != null && mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - // package revision numbers must match - return mUpdatePkg.getRevision().equals(pkg.getRevision()); - } - return false; - } - - /** - * Checks whether too {@link PkgItem} are the same. - * This checks both items have the same state, both main package are similar - * and that they have the same updating packages. - */ - public boolean isSameItemAs(PkgItem item) { - if (this == item) { - return true; - } - boolean same = this.mState == item.mState; - if (same) { - same = isSameMainPackageAs(item.getMainPackage()); - } - - if (same) { - // check updating packages are the same - Package p1 = this.mUpdatePkg; - Package p2 = item.getUpdatePkg(); - same = (p1 == p2) || (p1 == null && p2 == null) || (p1 != null && p2 != null); - - if (same && p1 != null) { - same = p1.canBeUpdatedBy(p2) == UpdateInfo.NOT_UPDATE; - } - } - - return same; - } - - /** - * Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package - * and update package must be the similar. - */ - @Override - public boolean equals(Object obj) { - return (obj instanceof PkgItem) && this.isSameItemAs((PkgItem) obj); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mState == null) ? 0 : mState.hashCode()); - result = prime * result + ((mMainPkg == null) ? 0 : mMainPkg.hashCode()); - result = prime * result + ((mUpdatePkg == null) ? 0 : mUpdatePkg.hashCode()); - return result; - } - - /** - * Check whether the 'pkg' argument is an update for this package. - * If it is, record it as an updating package. - * If there's already an updating package, only keep the most recent update. - * Returns true if it is update (even if there was already an update and this - * ended up not being the most recent), false if incompatible or not an update. - * - * This should only be used for installed packages. - */ - public boolean mergeUpdate(Package pkg) { - if (mUpdatePkg == pkg) { - return true; - } - if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { - if (mUpdatePkg == null) { - mUpdatePkg = pkg; - } else if (mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { - // If we have more than one, keep only the most recent update - mUpdatePkg = pkg; - } - return true; - } - - return false; - } - - public void removeUpdate() { - mUpdatePkg = null; - } - - /** Returns a string representation of this item, useful when debugging. */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('<'); - - if (mChecked) { - sb.append(" * "); //$NON-NLS-1$ - } - - sb.append(mState.toString()); - - if (mMainPkg != null) { - sb.append(", pkg:"); //$NON-NLS-1$ - sb.append(mMainPkg.toString()); - } - - if (mUpdatePkg != null) { - sb.append(", updated by:"); //$NON-NLS-1$ - sb.append(mUpdatePkg.toString()); - } - - sb.append('>'); - return sb.toString(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterLogic.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterLogic.java deleted file mode 100644 index ff2000fa..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterLogic.java +++ /dev/null @@ -1,1568 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.updater; - -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.internal.repository.packages.BuildToolPackage; -import com.android.sdklib.internal.repository.packages.DocPackage; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.IExactApiLevelDependency; -import com.android.sdklib.internal.repository.packages.IMinApiLevelDependency; -import com.android.sdklib.internal.repository.packages.IMinPlatformToolsDependency; -import com.android.sdklib.internal.repository.packages.IMinToolsDependency; -import com.android.sdklib.internal.repository.packages.IPlatformDependency; -import com.android.sdklib.internal.repository.packages.MinToolsPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SamplePackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IdDisplay; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * The logic to compute which packages to install, based on the choices - * made by the user. This adds required packages as needed. - *

- * When the user doesn't provide a selection, looks at local package to find - * those that can be updated and compute dependencies too. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkUpdaterLogic { - - private final IUpdaterData mUpdaterData; - - public SdkUpdaterLogic(IUpdaterData updaterData) { - mUpdaterData = updaterData; - } - - /** - * Retrieves an unfiltered list of all remote archives. - * The archives are guaranteed to be compatible with the current platform. - */ - public List getAllRemoteArchives( - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - List remotePkgs = new ArrayList(); - SdkSource[] remoteSources = sources.getAllSources(); - fetchRemotePackages(remotePkgs, remoteSources); - - ArrayList archives = new ArrayList(); - for (Package remotePkg : remotePkgs) { - // Only look for non-obsolete updates unless requested to include them - if (includeAll || !remotePkg.isObsolete()) { - // Found a suitable update. Only accept the remote package - // if it provides at least one compatible archive - - addArchives: - for (Archive a : remotePkg.getArchives()) { - if (a.isCompatible()) { - - // If we're trying to add a package for revision N, - // make sure we don't also have a package for revision N-1. - for (int i = archives.size() - 1; i >= 0; i--) { - Package pkgFound = archives.get(i).getParentPackage(); - if (pkgFound.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // This package can update one we selected earlier. - // Remove the one that can be updated by this new one. - archives.remove(i); - } else if (remotePkg.canBeUpdatedBy(pkgFound) == UpdateInfo.UPDATE) { - // There is a package in the list that is already better - // than the one we want to add, so don't add it. - break addArchives; - } - } - - archives.add(a); - break; - } - } - } - } - - ArrayList result = new ArrayList(); - - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - for (Archive a : archives) { - insertArchive(a, - result, - archives, - remotePkgs, - remoteSources, - localArchives, - false /*automated*/); - } - - return result; - } - - /** - * Compute which packages to install by taking the user selection - * and adding required packages as needed. - * - * When the user doesn't provide a selection, looks at local packages to find - * those that can be updated and compute dependencies too. - */ - public List computeUpdates( - Collection selectedArchives, - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - List archives = new ArrayList(); - List remotePkgs = new ArrayList(); - SdkSource[] remoteSources = sources.getAllSources(); - - // Create ArchiveInfos out of local (installed) packages. - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - // If we do not have a specific list of archives to install (that is the user - // selected "update all" rather than request specific packages), then we try to - // find updates based on the *existing* packages. - if (selectedArchives == null) { - selectedArchives = findUpdates( - localArchives, - remotePkgs, - remoteSources, - includeAll); - } - - // Once we have a list of packages to install, we try to solve all their - // dependencies by automatically adding them to the list of things to install. - // This works on the list provided either by the user directly or the list - // computed from potential updates. - for (Archive a : selectedArchives) { - insertArchive(a, - archives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - false /*automated*/); - } - - // Finally we need to look at *existing* packages which are not being updated - // and check if they have any missing dependencies and suggest how to fix - // these dependencies. - fixMissingLocalDependencies( - archives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - return archives; - } - - private double getRevisionRank(FullRevision rev) { - int p = rev.isPreview() ? 999 : 999 - rev.getPreview(); - return rev.getMajor() + - rev.getMinor() / 1000.d + - rev.getMicro() / 1000000.d + - p / 1000000000.d; - } - - /** - * Finds new packages that the user does not have in his/her local SDK - * and adds them to the list of archives to install. - *

- * The default is to only find "new" platforms, that is anything more - * recent than the highest platform currently installed. - * A side effect is that for an empty SDK install this will list *all* - * platforms available (since there's no "highest" installed platform.) - *

- * This also adds "silent" dependencies. For example the user probably - * needs to have at least one version of the build-tools package although - * there is nothing that directly depends on it. So if the user doesn't have - * any installed or selected version, selected the most recent one as a - * candidate for install. - * - * @param archives The in-out list of archives to install. Typically the - * list is not empty at first as it should contain any archives that is - * already scheduled for install. This method will add to the list. - * @param sources The list of all sources, to fetch them as necessary. - * @param localPkgs The list of all currently installed packages. - * @param includeAll When true, this will list all platforms. - * (included these lower than the highest installed one) as well as - * all obsolete packages of these platforms. - */ - public void addNewPlatforms( - Collection archives, - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - // Create ArchiveInfos out of local (installed) packages. - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - // Find the highest platform installed - double currentBuildToolScore = 0; - double currentPlatformScore = 0; - double currentSampleScore = 0; - double currentAddonScore = 0; - double currentDocScore = 0; - HashMap currentExtraScore = new HashMap(); - if (!includeAll) { - if (localPkgs != null) { - for (Package p : localPkgs) { - double rev = getRevisionRank(p.getRevision()); - int api = 0; - boolean isPreview = false; - if (p instanceof IAndroidVersionProvider) { - AndroidVersion vers = ((IAndroidVersionProvider) p).getAndroidVersion(); - api = vers.getApiLevel(); - isPreview = vers.isPreview(); - } - - // The score is 1000*api + (999 if preview) + rev - // This allows previews to rank above a non-preview and - // allows revisions to rank appropriately. - double score = api * 1000 + (isPreview ? 999 : 0) + rev; - - if (p instanceof BuildToolPackage) { - currentBuildToolScore = Math.max(currentBuildToolScore, score); - } else if (p instanceof PlatformPackage) { - currentPlatformScore = Math.max(currentPlatformScore, score); - } else if (p instanceof SamplePackage) { - currentSampleScore = Math.max(currentSampleScore, score); - } else if (p instanceof AddonPackage) { - currentAddonScore = Math.max(currentAddonScore, score); - } else if (p instanceof ExtraPackage) { - currentExtraScore.put(((ExtraPackage) p).getPath(), score); - } else if (p instanceof DocPackage) { - currentDocScore = Math.max(currentDocScore, score); - } - } - } - } - - SdkSource[] remoteSources = sources.getAllSources(); - ArrayList remotePkgs = new ArrayList(); - fetchRemotePackages(remotePkgs, remoteSources); - - Package suggestedDoc = null; - Package suggestedBuildTool = null; - - for (Package p : remotePkgs) { - // Skip obsolete packages unless requested to include them. - if (p.isObsolete() && !includeAll) { - continue; - } - - double rev = getRevisionRank(p.getRevision()); - int api = 0; - boolean isPreview = false; - if (p instanceof IAndroidVersionProvider) { - AndroidVersion vers = ((IAndroidVersionProvider) p).getAndroidVersion(); - api = vers.getApiLevel(); - isPreview = vers.isPreview(); - } - - double score = api * 1000 + (isPreview ? 999 : 0) + rev; - - boolean shouldAdd = false; - if (p instanceof BuildToolPackage) { - // We don't want all the build-tool packages, only the most recent one - // if not is currently installed. - if (currentBuildToolScore == 0 && score > currentBuildToolScore) { - suggestedBuildTool = p; - currentBuildToolScore = score; - } - } else if (p instanceof PlatformPackage) { - shouldAdd = score > currentPlatformScore; - } else if (p instanceof SamplePackage) { - shouldAdd = score > currentSampleScore; - } else if (p instanceof AddonPackage) { - shouldAdd = score > currentAddonScore; - } else if (p instanceof ExtraPackage) { - String key = ((ExtraPackage) p).getPath(); - shouldAdd = !currentExtraScore.containsKey(key) || - score > currentExtraScore.get(key).doubleValue(); - } else if (p instanceof DocPackage) { - // We don't want all the doc, only the most recent one - if (score > currentDocScore) { - suggestedDoc = p; - currentDocScore = score; - } - } - - if (shouldAdd) { - // We should suggest this package for installation. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - - if (p instanceof PlatformPackage && (score >= currentPlatformScore)) { - // We just added a new platform *or* we are visiting the highest currently - // installed platform. In either case we want to make sure it either has - // its own system image or that we provide one by default. - PlatformPackage pp = (PlatformPackage) p; - if (pp.getIncludedAbi() == null) { - for (Package p2 : remotePkgs) { - if (!(p2 instanceof SystemImagePackage) || - ((SystemImagePackage)p2).isPlatform() || - (p2.isObsolete() && !includeAll)) { - continue; - } - SystemImagePackage sip = (SystemImagePackage) p2; - if (sip.getAndroidVersion().equals(pp.getAndroidVersion())) { - for (Archive a : sip.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - } - } - - if (suggestedDoc != null) { - // We should suggest this package for installation. - for (Archive a : suggestedDoc.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - - if (suggestedBuildTool != null) { - // We should suggest this package for installation. - for (Archive a : suggestedBuildTool.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - /** - * Create a array of {@link ArchiveInfo} based on all local (already installed) - * packages. The array is always non-null but may be empty. - *

- * The local {@link ArchiveInfo} are guaranteed to have one non-null archive - * that you can retrieve using {@link ArchiveInfo#getNewArchive()}. - */ - public ArchiveInfo[] createLocalArchives(Package[] localPkgs) { - - if (localPkgs != null) { - ArrayList list = new ArrayList(); - for (Package p : localPkgs) { - // Only accept packages that have one compatible archive. - // Local package should have 1 and only 1 compatible archive anyway. - for (Archive a : p.getArchives()) { - if (a != null && a.isCompatible()) { - // We create an "installed" archive info to wrap the local package. - // Note that dependencies are not computed since right now we don't - // deal with more than one level of dependencies and installed archives - // are deemed implicitly accepted anyway. - list.add(new LocalArchiveInfo(a)); - } - } - } - - return list.toArray(new ArchiveInfo[list.size()]); - } - - return new ArchiveInfo[0]; - } - - /** - * Find suitable updates to all current local packages. - *

- * Returns a list of potential updates for *existing* packages. This does NOT solve - * dependencies for the new packages. - *

- * Always returns a non-null collection, which can be empty. - */ - private Collection findUpdates( - ArchiveInfo[] localArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - boolean includeAll) { - ArrayList updates = new ArrayList(); - - fetchRemotePackages(remotePkgs, remoteSources); - - for (ArchiveInfo ai : localArchives) { - Archive na = ai.getNewArchive(); - if (na == null) { - continue; - } - Package localPkg = na.getParentPackage(); - - for (Package remotePkg : remotePkgs) { - // Only look for non-obsolete updates unless requested to include them - if ((includeAll || !remotePkg.isObsolete()) && - localPkg.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // Found a suitable update. Only accept the remote package - // if it provides at least one compatible archive - - addArchives: - for (Archive a : remotePkg.getArchives()) { - if (a.isCompatible()) { - - // If we're trying to add a package for revision N, - // make sure we don't also have a package for revision N-1. - for (int i = updates.size() - 1; i >= 0; i--) { - Package pkgFound = updates.get(i).getParentPackage(); - if (pkgFound.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // This package can update one we selected earlier. - // Remove the one that can be updated by this new one. - updates.remove(i); - } else if (remotePkg.canBeUpdatedBy(pkgFound) == - UpdateInfo.UPDATE) { - // There is a package in the list that is already better - // than the one we want to add, so don't add it. - break addArchives; - } - } - - updates.add(a); - break; - } - } - } - } - } - - return updates; - } - - /** - * Check all local archives which are NOT being updated and see if they - * miss any dependency. If they do, try to fix that dependency by selecting - * an appropriate package. - */ - private void fixMissingLocalDependencies( - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - nextLocalArchive: for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - Package p = a == null ? null : a.getParentPackage(); - if (p == null) { - continue; - } - - // Is this local archive being updated? - for (ArchiveInfo ai2 : outArchives) { - if (ai2.getReplaced() == a) { - // this new archive will replace the current local one, - // so we don't have to care about fixing dependencies (since the - // new archive should already have had its dependencies resolved) - continue nextLocalArchive; - } - } - - // find dependencies for the local archive and add them as needed - // to the outArchives collection. - ArchiveInfo[] deps = findDependency(p, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (deps != null) { - // The already installed archive has a missing dependency, which we - // just selected for install. Make sure we remember the dependency - // so that we can enforce it later in the UI. - for (ArchiveInfo aid : deps) { - aid.addDependencyFor(ai); - } - } - } - } - - private ArchiveInfo insertArchive(Archive archive, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives, - boolean automated) { - Package p = archive.getParentPackage(); - - // Is this an update? - Archive updatedArchive = null; - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package lp = a.getParentPackage(); - - if (lp.canBeUpdatedBy(p) == UpdateInfo.UPDATE) { - updatedArchive = a; - } - } - } - - // Find dependencies and adds them as needed to outArchives - ArchiveInfo[] deps = findDependency(p, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - // Make sure it's not a dup - ArchiveInfo ai = null; - - for (ArchiveInfo ai2 : outArchives) { - Archive a2 = ai2.getNewArchive(); - if (a2 != null && a2.getParentPackage().sameItemAs(archive.getParentPackage())) { - ai = ai2; - break; - } - } - - if (ai == null) { - ai = new ArchiveInfo( - archive, //newArchive - updatedArchive, //replaced - deps //dependsOn - ); - outArchives.add(ai); - } - - if (deps != null) { - for (ArchiveInfo d : deps) { - d.addDependencyFor(ai); - } - } - - return ai; - } - - /** - * Resolves dependencies for a given package. - * - * Returns null if no dependencies were found. - * Otherwise return an array of {@link ArchiveInfo}, which is guaranteed to have - * at least size 1 and contain no null elements. - */ - private ArchiveInfo[] findDependency(Package pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - // Current dependencies can be: - // - addon: *always* depends on platform of same API level - // - platform: *might* depends on tools of rev >= min-tools-rev - // - extra: *might* depends on platform with api >= min-api-level - - Set aiFound = new HashSet(); - - if (pkg instanceof IPlatformDependency) { - ArchiveInfo ai = findPlatformDependency( - (IPlatformDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinToolsDependency) { - - ArchiveInfo ai = findToolsDependency( - (IMinToolsDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinPlatformToolsDependency) { - - ArchiveInfo ai = findPlatformToolsDependency( - (IMinPlatformToolsDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinApiLevelDependency) { - - ArchiveInfo ai = findMinApiLevelDependency( - (IMinApiLevelDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IExactApiLevelDependency) { - - ArchiveInfo ai = findExactApiLevelDependency( - (IExactApiLevelDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (!aiFound.isEmpty()) { - ArchiveInfo[] result = aiFound.toArray(new ArchiveInfo[aiFound.size()]); - Arrays.sort(result); - return result; - } - - return null; - } - - /** - * Resolves dependencies on tools. - * - * A platform or an extra package can both have a min-tools-rev, in which case it - * depends on having a tools package of the requested revision. - * Finds the tools dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - public ArchiveInfo findToolsDependency( - IMinToolsDependency pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - FullRevision rev = pkg.getMinToolsRevision(); - - if (rev.equals(MinToolsPackage.MIN_TOOLS_REV_NOT_SPECIFIED)) { - // Well actually there's no requirement. - return null; - } - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // The dependency is already scheduled for install, nothing else to do. - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - FullRevision localRev = rev; - Archive localArch = null; - for (Package p : remotePkgs) { - if (p instanceof ToolPackage) { - FullRevision r = ((ToolPackage) p).getRevision(); - if (r.compareTo(localRev) >= 0) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - localRev = r; - localArch = a; - break; - } - } - } - } - } - if (localArch != null) { - return insertArchive(localArch, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingArchiveInfo(MissingArchiveInfo.TITLE_TOOL, rev); - } - - /** - * Resolves dependencies on platform-tools. - * - * A tool package can have a min-platform-tools-rev, in which case it depends on - * having a platform-tool package of the requested revision. - * Finds the platform-tool dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - public ArchiveInfo findPlatformToolsDependency( - IMinPlatformToolsDependency pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - FullRevision rev = pkg.getMinPlatformToolsRevision(); - boolean findMax = false; - int compareThreshold = 0; - ArchiveInfo aiMax = null; - Archive aMax = null; - - if (rev.equals(IMinPlatformToolsDependency.MIN_PLATFORM_TOOLS_REV_INVALID)) { - // The requirement is invalid, which is not supposed to happen since this - // property is mandatory. However in a typical upgrade scenario we can end - // up with the previous updater managing a new package and not dealing - // correctly with the new unknown property. - // So instead we parse all the existing and remote packages and try to find - // the max available revision and we'll use it. - findMax = true; - // When findMax is false, we want r.compareTo(rev) >= 0. - // When findMax is true, we want r.compareTo(rev) > 0 (so >= 1). - compareThreshold = 1; - } - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - if (findMax && r.compareTo(rev) > compareThreshold) { - rev = r; - aiMax = ai; - } else if (!findMax && r.compareTo(rev) >= compareThreshold) { - // We found one already installed. - return null; - } - } - } - } - - // Because of previews, we can have more than 1 choice, so get the local max. - FullRevision localRev = rev; - ArchiveInfo localAiMax = null; - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - // If computing dependencies for a non-preview package, don't offer preview dependencies - if (r.isPreview() && !rev.isPreview()) { - continue; - } - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = ai; - } - } - } - } - if (localAiMax != null) { - if (findMax) { - rev = localRev; - aiMax = localAiMax; - } else { - // The dependency is already scheduled for install, nothing else to do. - return localAiMax; - } - } - - - // Otherwise look in the selected archives. - localRev = rev; - Archive localAMax = null; - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - // If computing dependencies for a non-preview package, don't offer preview dependencies - if (r.isPreview() && !rev.isPreview()) { - continue; - } - - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = null; - localAMax = a; - } - } - } - if (localAMax != null) { - if (findMax) { - rev = localRev; - aiMax = null; - aMax = localAMax; - } else { - // It's not already in the list of things to install, so add it now - return insertArchive(localAMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - localRev = rev; - localAMax = null; - for (Package p : remotePkgs) { - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - // If computing dependencies for a non-preview package, don't offer preview dependencies - if (r.isPreview() && !rev.isPreview()) { - continue; - } - - if (r.compareTo(rev) >= 0) { - // Make sure there's at least one valid archive here - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = null; - localAMax = a; - break; - } - } - } - } - } - } - if (localAMax != null) { - if (findMax) { - rev = localRev; - aiMax = null; - aMax = localAMax; - } else { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - return insertArchive(localAMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - - if (findMax) { - if (aMax != null) { - return insertArchive(aMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } else if (aiMax != null) { - return aiMax; - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this package depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingArchiveInfo(MissingArchiveInfo.TITLE_PLATFORM_TOOL, rev); - } - - /** - * Resolves dependencies on platform for an add-on. - * Resolves dependencies on a system-image on its base platform or add-on. - * - * An add-on depends on having a platform with the same API level. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - public ArchiveInfo findPlatformDependency( - IPlatformDependency pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - AndroidVersion v = pkg.getAndroidVersion(); - - - // The dependency package must be a PlatformPackage or an AddonPackage. - // For an add-on, we also need to have the same vendor and name-id. - Class expectedClass = PlatformPackage.class; - IdDisplay addonVendor = null; - IdDisplay addonTag = null; - if (pkg instanceof SystemImagePackage && !((SystemImagePackage) pkg).isPlatform()) { - expectedClass = AddonPackage.class; - addonVendor = ((SystemImagePackage) pkg).getAddonVendor(); - addonTag = ((SystemImagePackage) pkg).getTag(); - } - - // Find a platform or addon that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (expectedClass.isInstance(p)) { - if (v.equals(((IAndroidVersionProvider) p).getAndroidVersion())) { - if (addonVendor != null && addonTag != null && p instanceof AddonPackage) { - if (!((AddonPackage) p).getVendorId().equals(addonVendor.getId()) || - !((AddonPackage) p).getNameId().equals(addonTag.getId())) { - continue; - } - } - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (expectedClass.isInstance(p)) { - if (v.equals(((IAndroidVersionProvider) p).getAndroidVersion())) { - if (addonVendor != null && addonTag != null && p instanceof AddonPackage) { - if (!((AddonPackage) p).getVendorId().equals(addonVendor.getId()) || - !((AddonPackage) p).getNameId().equals(addonTag.getId())) { - continue; - } - } - // The dependency is already scheduled for install, nothing else to do. - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (expectedClass.isInstance(p)) { - if (v.equals(((IAndroidVersionProvider) p).getAndroidVersion())) { - if (addonVendor != null && addonTag != null && p instanceof AddonPackage) { - if (!((AddonPackage) p).getVendorId().equals(addonVendor.getId()) || - !((AddonPackage) p).getNameId().equals(addonTag.getId())) { - continue; - } - } - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (expectedClass.isInstance(p)) { - if (v.equals(((IAndroidVersionProvider) p).getAndroidVersion())) { - if (addonVendor != null && addonTag != null && p instanceof AddonPackage) { - if (!((AddonPackage) p).getVendorId().equals(addonVendor.getId()) || - !((AddonPackage) p).getNameId().equals(addonTag.getId())) { - continue; - } - } - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this addon depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(pkg.getAndroidVersion()); - } - - /** - * Resolves platform dependencies for extras. - * An extra depends on having a platform with a minimun API level. - * - * We try to return the highest API level available above the specified minimum. - * Note that installed packages have priority so if one installed platform satisfies - * the dependency, we'll use it even if there's a higher API platform available but - * not installed yet. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findMinApiLevelDependency( - IMinApiLevelDependency pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - int api = pkg.getMinApiLevel(); - - if (api == IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED) { - return null; - } - - // Find a platform that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - int foundApi = 0; - ArchiveInfo foundAi = null; - - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - foundApi = api; - foundAi = ai; - } - } - } - } - } - - if (foundAi != null) { - // The dependency is already scheduled for install, nothing else to do. - return foundAi; - } - - // Otherwise look in the selected archives *or* available remote packages - // and takes the best out of the two sets. - foundApi = 0; - Archive foundArchive = null; - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - foundApi = api; - foundArchive = a; - } - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - foundApi = api; - foundArchive = a; - } - } - } - } - } - } - - if (foundArchive != null) { - // It's not already in the list of things to install, so add it now - return insertArchive(foundArchive, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(new AndroidVersion(api, null /*codename*/)); - } - - /** - * Resolves platform dependencies for add-ons. - * An add-ons depends on having a platform with an exact specific API level. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - public ArchiveInfo findExactApiLevelDependency( - IExactApiLevelDependency pkg, - Collection outArchives, - Collection selectedArchives, - Collection remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - int api = pkg.getExactApiLevel(); - - if (api == IExactApiLevelDependency.API_LEVEL_INVALID) { - return null; - } - - // Find a platform that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(new AndroidVersion(api, null /*codename*/)); - } - - /** - * Fetch all remote packages only if really needed. - *

- * This method takes a list of sources. Each source is only fetched once -- that is each - * source keeps the list of packages that we fetched from the remote XML file. If the list - * is null, it means this source has never been fetched so we'll do it once here. Otherwise - * we rely on the cached list of packages from this source. - *

- * This method also takes a remote package list as input, which it will fill out. - * If a source has already been fetched, we'll add its packages to the remote package list - * if they are not already present. Otherwise, the source will be fetched and the packages - * added to the list. - * - * @param remotePkgs An in-out list of packages available from remote sources. - * This list must not be null. - * It can be empty or already contain some packages. - * @param remoteSources A list of available remote sources to fetch from. - */ - protected void fetchRemotePackages( - final Collection remotePkgs, - final SdkSource[] remoteSources) { - if (!remotePkgs.isEmpty()) { - return; - } - - // First check if there's any remote source we need to fetch. - // This will bring the task window, so we rather not display it unless - // necessary. - boolean needsFetch = false; - for (final SdkSource remoteSrc : remoteSources) { - Package[] pkgs = remoteSrc.getPackages(); - if (pkgs == null) { - // This source has never been fetched. We'll do it below. - needsFetch = true; - } else { - // This source has already been fetched and we know its package list. - // We still need to make sure all of its packages are present in the - // remotePkgs list. - - nextPackage: for (Package pkg : pkgs) { - for (Archive a : pkg.getArchives()) { - // Only add a package if it contains at least one compatible archive - // and is not already in the remote package list. - if (a.isCompatible()) { - if (!remotePkgs.contains(pkg)) { - remotePkgs.add(pkg); - continue nextPackage; - } - } - } - } - } - } - - if (!needsFetch) { - return; - } - - final boolean forceHttp = mUpdaterData.getSettingsController().getSettings().getForceHttp(); - - mUpdaterData.getTaskFactory().start("Refresh Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - for (SdkSource remoteSrc : remoteSources) { - Package[] pkgs = remoteSrc.getPackages(); - - if (pkgs == null) { - remoteSrc.load(mUpdaterData.getDownloadCache(), monitor, forceHttp); - pkgs = remoteSrc.getPackages(); - } - - if (pkgs != null) { - nextPackage: for (Package pkg : pkgs) { - for (Archive a : pkg.getArchives()) { - // Only add a package if it contains at least one compatible archive - // and is not already in the remote package list. - if (a.isCompatible()) { - if (!remotePkgs.contains(pkg)) { - remotePkgs.add(pkg); - continue nextPackage; - } - } - } - } - } - } - } - }); - } - - - /** - * A {@link LocalArchiveInfo} is an {@link ArchiveInfo} that wraps an already installed - * "local" package/archive. - *

- * In this case, the "new Archive" is still expected to be non null and the - * "replaced Archive" is null. Installed archives are always accepted and never - * rejected. - *

- * Dependencies are not set. - */ - private static class LocalArchiveInfo extends ArchiveInfo { - - public LocalArchiveInfo(Archive localArchive) { - super(localArchive, null /*replaced*/, null /*dependsOn*/); - } - - /** Installed archives are always accepted. */ - @Override - public boolean isAccepted() { - return true; - } - - /** Installed archives are never rejected. */ - @Override - public boolean isRejected() { - return false; - } - } - - /** - * A {@link MissingPlatformArchiveInfo} is an {@link ArchiveInfo} that represents a - * package/archive that we really need as a dependency but that we don't have. - *

- * This is currently used for addons and extras in case we can't find a matching base platform. - *

- * This kind of archive has specific properties: the new archive to install is null, - * there are no dependencies and no archive is being replaced. The info can never be - * accepted and is always rejected. - */ - private static class MissingPlatformArchiveInfo extends ArchiveInfo { - - private final AndroidVersion mVersion; - - /** - * Constructs a {@link MissingPlatformArchiveInfo} that will indicate the - * given platform version is missing. - */ - public MissingPlatformArchiveInfo(AndroidVersion version) { - super(null /*newArchive*/, null /*replaced*/, null /*dependsOn*/); - mVersion = version; - } - - /** Missing archives are never accepted. */ - @Override - public boolean isAccepted() { - return false; - } - - /** Missing archives are always rejected. */ - @Override - public boolean isRejected() { - return true; - } - - @Override - public String getShortDescription() { - return String.format("Missing SDK Platform Android%1$s, API %2$d", - mVersion.isPreview() ? " Preview" : "", - mVersion.getApiLevel()); - } - } - - /** - * A {@link MissingArchiveInfo} is an {@link ArchiveInfo} that represents a - * package/archive that we really need as a dependency but that we don't have. - *

- * This is currently used for extras in case we can't find a matching tool revision - * or when a platform-tool is missing. - *

- * This kind of archive has specific properties: the new archive to install is null, - * there are no dependencies and no archive is being replaced. The info can never be - * accepted and is always rejected. - */ - private static class MissingArchiveInfo extends ArchiveInfo { - - private final FullRevision mRevision; - private final String mTitle; - - public static final String TITLE_TOOL = "Tools"; - public static final String TITLE_PLATFORM_TOOL = "Platform-tools"; - - /** - * Constructs a {@link MissingPlatformArchiveInfo} that will indicate the - * given platform version is missing. - * - * @param title Typically "Tools" or "Platform-tools". - * @param revision The required revision. - */ - public MissingArchiveInfo(String title, FullRevision revision) { - super(null /*newArchive*/, null /*replaced*/, null /*dependsOn*/); - mTitle = title; - mRevision = revision; - } - - /** Missing archives are never accepted. */ - @Override - public boolean isAccepted() { - return false; - } - - /** Missing archives are always rejected. */ - @Override - public boolean isRejected() { - return true; - } - - @Override - public String getShortDescription() { - return String.format("Missing Android SDK %1$s, revision %2$s", - mTitle, - mRevision.toShortString()); - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterNoWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterNoWindow.java deleted file mode 100644 index 8183e1bc..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SdkUpdaterNoWindow.java +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (C) 2010 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.internal.repository.updater; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.utils.ILogger; -import com.android.utils.IReaderLogger; -import com.android.utils.NullLogger; -import com.android.utils.Pair; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -/** - * Performs an update using only a non-interactive console output with no GUI. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SdkUpdaterNoWindow { - - /** The {@link UpdaterData} to use. */ - private final UpdaterData mUpdaterData; - /** The {@link ILogger} logger to use. */ - private final ILogger mSdkLog; - /** The reply to any question asked by the update process. Currently this will - * be yes/no for ability to replace modified samples or restart ADB. */ - private final boolean mForce; - - /** - * Creates an UpdateNoWindow object that will update using the given SDK root - * and outputs to the given SDK logger. - * - * @param osSdkRoot The OS path of the SDK folder to update. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @param sdkLog A logger object, that should ideally output to a write-only console. - * @param force The reply to any question asked by the update process. Currently this will - * be yes/no for ability to replace modified samples or restart ADB. - * @param useHttp True to force using HTTP instead of HTTPS for downloads. - * @param proxyPort An optional HTTP/HTTPS proxy port. Can be null. - * @param proxyHost An optional HTTP/HTTPS proxy host. Can be null. - */ - public SdkUpdaterNoWindow(String osSdkRoot, - SdkManager sdkManager, - ILogger sdkLog, - boolean force, - boolean useHttp, - String proxyHost, - String proxyPort) { - mSdkLog = sdkLog; - mForce = force; - mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); - - // Read and apply settings from settings file, so that http/https proxy is set - // and let the command line args override them as necessary. - SettingsController settingsController = mUpdaterData.getSettingsController(); - settingsController.loadSettings(); - settingsController.applySettings(); - setupProxy(proxyHost, proxyPort); - - // Change the in-memory settings to force the http/https mode - settingsController.setSetting(ISettingsPage.KEY_FORCE_HTTP, useHttp); - - // Use a factory that only outputs to the given ILogger. - mUpdaterData.setTaskFactory(new ConsoleTaskFactory()); - - // Check that the AVD Manager has been correctly initialized. This is done separately - // from the constructor in the GUI-based UpdaterWindowImpl to give time to the UI to - // initialize before displaying a message box. Since we don't have any GUI here - // we can call it whenever we want. - if (mUpdaterData.checkIfInitFailed()) { - return; - } - - // Setup the default sources including the getenv overrides. - mUpdaterData.setupDefaultSources(); - - mUpdaterData.getLocalSdkParser().parseSdk( - osSdkRoot, - sdkManager, - new NullTaskMonitor(sdkLog)); - } - - /** - * Performs the actual update. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} to limit the type of packages - * we can update. A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - * @param acceptLicense SDK licenses to automatically accept. - * @deprecated Use {@link #updateAll(java.util.ArrayList, boolean, boolean, String, boolean)} - * instead - */ - @Deprecated - public void updateAll( - ArrayList pkgFilter, - boolean includeAll, - boolean dryMode, - String acceptLicense) { - updateAll(pkgFilter, includeAll, dryMode, acceptLicense, false); - } - - /** - * Performs the actual update. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} to limit the type of packages - * we can update. A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - * @param acceptLicense SDK licenses to automatically accept. - * @param includeDependencies If true, also include any required dependencies - */ - public void updateAll( - ArrayList pkgFilter, - boolean includeAll, - boolean dryMode, - String acceptLicense, - boolean includeDependencies) { - mUpdaterData.updateOrInstallAll_NoGUI(pkgFilter, includeAll, dryMode, acceptLicense, - includeDependencies); - } - - /** - * Lists remote packages available for install using 'android update sdk --no-ui'. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @param extendedOutput True to display more details on each package. - */ - public void listRemotePackages(boolean includeAll, boolean extendedOutput) { - mUpdaterData.listRemotePackages_NoGUI(includeAll, extendedOutput); - } - - /** - * Installs a platform package given its target hash string. - *

- * This does not work for add-ons right now, just basic platforms. - * - * @param hashString The hash string of the platform to install. - * @return A boolean indicating whether the installation was successful (meaning the package - * was either already present, or got installed or updated properly) and a {@link File} - * with the path to the root folder of the package. The file is null when the boolean - * is false, otherwise it should point to an existing valid folder. - */ - public Pair installPlatformPackage(String hashString) { - - // TODO right now we really need the caller to use a reader-logger to - // handle license confirmations. This isn't optimal and should be addressed - // when we provide a proper UI for this. - assert mSdkLog instanceof IReaderLogger; - - SdkManager sm = mUpdaterData.getSdkManager(); - IAndroidTarget target = sm.getTargetFromHashString(hashString); - - if (target == null) { - // Otherwise try to install it. - // This currently only works for platforms since the package's "install id" - // is an exactly match with the IAndroidTarget hash string. - ArrayList filter = new ArrayList(); - filter.add(hashString); - List installed = mUpdaterData.updateOrInstallAll_NoGUI( - filter, - true, //includeAll - false, //dryMode - null); //acceptLicense - - if (installed != null) { - sm.reloadSdk(new NullLogger()); - target = sm.getTargetFromHashString(hashString); - } - } - - if (target != null) { - // Return existing target - return Pair.of(Boolean.TRUE, new File(target.getLocation())); - } - - return null; - } - - // ----- - - /** - * Sets both the HTTP and HTTPS proxy system properties, overriding the ones - * from the settings with these values if they are defined. - */ - private void setupProxy(String proxyHost, String proxyPort) { - - // The system property constants can be found in the Java SE documentation at - // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html - final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ - - Properties props = System.getProperties(); - - if (proxyHost != null && !proxyHost.isEmpty()) { - props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); - props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); - } - if (proxyPort != null && !proxyPort.isEmpty()) { - props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); - props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); - } - } - - /** - * A custom implementation of {@link ITaskFactory} that - * provides {@link ConsoleTaskMonitor} objects. - */ - private class ConsoleTaskFactory implements ITaskFactory { - @Override - public void start(String title, ITask task) { - start(title, null /*parentMonitor*/, task); - } - - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - if (parentMonitor == null) { - task.run(new ConsoleTaskMonitor(title, task)); - } else { - // Use all the reminder of the parent monitor. - if (parentMonitor.getProgressMax() == 0) { - parentMonitor.setProgressMax(1); - } - - ITaskMonitor sub = parentMonitor.createSubMonitor( - parentMonitor.getProgressMax() - parentMonitor.getProgress()); - try { - task.run(sub); - } finally { - int delta = - sub.getProgressMax() - sub.getProgress(); - if (delta > 0) { - sub.incProgress(delta); - } - } - } - } - } - - /** - * A custom implementation of {@link ITaskMonitor} that defers all output to the - * super {@link SdkUpdaterNoWindow#mSdkLog}. - */ - private class ConsoleTaskMonitor implements ITaskMonitor { - - private static final double MAX_COUNT = 10000.0; - private double mIncCoef = 0; - private double mValue = 0; - private String mLastDesc = null; - private String mLastProgressBase = null; - - /** - * Creates a new {@link ConsoleTaskMonitor} with the given title. - */ - public ConsoleTaskMonitor(String title, ITask task) { - mSdkLog.info("%s:\n", title); - } - - /** - * Sets the description in the current task dialog. - */ - @Override - public void setDescription(String format, Object...args) { - - String last = mLastDesc; - String line = String.format(" " + format, args); //$NON-NLS-1$ - - // If the description contains a %, it generally indicates a recurring - // progress so we want a \r at the end. - int pos = line.indexOf('%'); - if (pos > -1) { - String base = line.trim(); - if (mLastProgressBase != null && base.startsWith(mLastProgressBase)) { - line = " " + base.substring(mLastProgressBase.length()); //$NON-NLS-1$ - } - line += '\r'; - } else { - mLastProgressBase = line.trim(); - line += '\n'; - } - - // Skip line if it's the same as the last one. - if (last != null && last.equals(line.trim())) { - return; - } - mLastDesc = line.trim(); - - // If the last line terminated with a \r but the new one doesn't, we need to - // insert a \n to avoid erasing the previous line. - if (last != null && - last.endsWith("\r") && //$NON-NLS-1$ - !line.endsWith("\r")) { //$NON-NLS-1$ - line = '\n' + line; - } - - mSdkLog.info("%s", line); //$NON-NLS-1$ - } - - @Override - public void log(String format, Object...args) { - setDescription(" " + format, args); //$NON-NLS-1$ - } - - @Override - public void logError(String format, Object...args) { - setDescription(format, args); - } - - @Override - public void logVerbose(String format, Object...args) { - // The ConsoleTask does not display verbose log messages. - } - - // --- ILogger --- - - @Override - public void error(@Nullable Throwable t, @Nullable String errorFormat, Object... args) { - mSdkLog.error(t, errorFormat, args); - } - - @Override - public void warning(@NonNull String warningFormat, Object... args) { - mSdkLog.warning(warningFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - mSdkLog.info(msgFormat, args); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - mSdkLog.verbose(msgFormat, args); - } - - /** - * Sets the max value of the progress bar. - * - * Weird things will happen if setProgressMax is called multiple times - * *after* {@link #incProgress(int)}: we don't try to adjust it on the - * fly. - */ - @Override - public void setProgressMax(int max) { - assert max > 0; - // Always set the dialog's progress max to 10k since it only handles - // integers and we want to have a better inner granularity. Instead - // we use the max to compute a coefficient for inc deltas. - mIncCoef = max > 0 ? MAX_COUNT / max : 0; - assert mIncCoef > 0; - } - - @Override - public int getProgressMax() { - return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0; - } - - /** - * Increments the current value of the progress bar. - */ - @Override - public void incProgress(int delta) { - if (delta > 0 && mIncCoef > 0) { - internalIncProgress(delta * mIncCoef); - } - } - - private void internalIncProgress(double realDelta) { - mValue += realDelta; - // max value is 10k, so 10k/100 == 100%. - // Experimentation shows that it is not really useful to display this - // progression since during download the description line will change. - // mSdkLog.printf(" [%3d%%]\r", ((int)mValue) / 100); - } - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - */ - @Override - public int getProgress() { - assert mIncCoef > 0; - return mIncCoef > 0 ? (int)(mValue / mIncCoef) : 0; - } - - /** - * Returns true if the "Cancel" button was selected. - */ - @Override - public boolean isCancelRequested() { - return false; - } - - /** - * Display a yes/no question dialog box. - * - * This implementation allow this to be called from any thread, it - * makes sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - @Override - public boolean displayPrompt(final String title, final String message) { - // TODO Make it interactive if mForce==false - mSdkLog.info("\n%1$s\n%2$s\n%3$s", //$NON-NLS-1$ - title, - message, - mForce ? "--force used, will reply yes\n" : - "Note: you can use --force to override to yes.\n"); - if (mForce) { - return true; - } - - while (true) { - mSdkLog.info("%1$s", "[y/n] =>"); //$NON-NLS-1$ - try { - byte[] readBuffer = new byte[2048]; - String reply = readLine(readBuffer).trim(); - mSdkLog.info("\n"); //$NON-NLS-1$ - if (!reply.isEmpty() && reply.length() <= 3) { - char c = reply.charAt(0); - if (c == 'y' || c == 'Y') { - return true; - } else if (c == 'n' || c == 'N') { - return false; - } - } - mSdkLog.info("Unknown reply '%s'. Please use y[es]/n[o].\n"); //$NON-NLS-1$ - - } catch (IOException e) { - // Exception. Be conservative and say no. - mSdkLog.info("\n"); //$NON-NLS-1$ - return false; - } - } - } - - /** - * Displays a prompt message to the user and read two values, - * login/password. - *

- * Asks user for login/password information. - *

- * This method shows a question in the standard output, asking for login - * and password.
- * Method Output:
- * Title
- * Message
- * Login: (Wait for user input)
- * Password: (Wait for user input)
- *

- * - * @param title The title of the iteration. - * @param message The message to be displayed. - * @return A {@link Pair} holding the entered login and password. The - * first element is always the Login, and the - * second element is always the Password. This - * method will never return null, in case of error the pair will - * be filled with empty strings. - * @see ITaskMonitor#displayLoginCredentialsPrompt(String, String) - */ - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - String login = ""; //$NON-NLS-1$ - String password = ""; //$NON-NLS-1$ - String workstation = ""; //$NON-NLS-1$ - String domain = ""; //$NON-NLS-1$ - - mSdkLog.info("\n%1$s\n%2$s", title, message); - byte[] readBuffer = new byte[2048]; - try { - mSdkLog.info("\nLogin: "); - login = readLine(readBuffer); - mSdkLog.info("\nPassword: "); - password = readLine(readBuffer); - mSdkLog.info("\nIf your proxy uses NTLM authentication, provide the following information. Leave blank otherwise."); - mSdkLog.info("\nWorkstation: "); - workstation = readLine(readBuffer); - mSdkLog.info("\nDomain: "); - domain = readLine(readBuffer); - - /* - * TODO: Implement a way to don't echo the typed password On - * Java 5 there's no simple way to do this. There's just a - * workaround which is output backspaces on each keystroke. - * A good alternative is to use Java 6 java.io.Console - */ - } catch (IOException e) { - // Reset login/pass to empty Strings. - login = ""; //$NON-NLS-1$ - password = ""; //$NON-NLS-1$ - workstation = ""; //$NON-NLS-1$ - domain = ""; //$NON-NLS-1$ - //Just print the error to console. - mSdkLog.info("\nError occurred during login/pass query: %s\n", e.getMessage()); - } - - return new UserCredentials(login, password, workstation, domain); - } - - /** - * Reads current console input in the given buffer. - * - * @param buffer Buffer to hold the user input. Must be larger than the largest - * expected input. Cannot be null. - * @return A new string. May be empty but not null. - * @throws IOException in case the buffer isn't long enough. - */ - private String readLine(byte[] buffer) throws IOException { - - int count; - if (mSdkLog instanceof IReaderLogger) { - count = ((IReaderLogger) mSdkLog).readLine(buffer); - } else { - count = System.in.read(buffer); - } - - // is the input longer than the buffer? - if (count == buffer.length && buffer[count-1] != 10) { - throw new IOException(String.format( - "Input is longer than the buffer size, (%1$s) bytes", buffer.length)); - } - - // ignore end whitespace - while (count > 0 && (buffer[count-1] == '\r' || buffer[count-1] == '\n')) { - count--; - } - - return new String(buffer, 0, count); - } - - /** - * Creates a sub-monitor that will use up to tickCount on the progress bar. - * tickCount must be 1 or more. - */ - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mIncCoef > 0; - assert tickCount > 0; - return new ConsoleSubTaskMonitor(this, null, mValue, tickCount * mIncCoef); - } - } - - private interface IConsoleSubTaskMonitor extends ITaskMonitor { - void subIncProgress(double realDelta); - } - - private static class ConsoleSubTaskMonitor implements IConsoleSubTaskMonitor { - - private final ConsoleTaskMonitor mRoot; - private final IConsoleSubTaskMonitor mParent; - private final double mStart; - private final double mSpan; - private double mSubValue; - private double mSubCoef; - - /** - * Creates a new sub task monitor which will work for the given range [start, start+span] - * in its parent. - * - * @param root The ProgressTask root - * @param parent The immediate parent. Can be the null or another sub task monitor. - * @param start The start value in the root's coordinates - * @param span The span value in the root's coordinates - */ - public ConsoleSubTaskMonitor(ConsoleTaskMonitor root, - IConsoleSubTaskMonitor parent, - double start, - double span) { - mRoot = root; - mParent = parent; - mStart = start; - mSpan = span; - mSubValue = start; - } - - @Override - public boolean isCancelRequested() { - return mRoot.isCancelRequested(); - } - - @Override - public void setDescription(String format, Object... args) { - mRoot.setDescription(format, args); - } - - @Override - public void log(String format, Object... args) { - mRoot.log(format, args); - } - - @Override - public void logError(String format, Object... args) { - mRoot.logError(format, args); - } - - @Override - public void logVerbose(String format, Object... args) { - mRoot.logVerbose(format, args); - } - - @Override - public void setProgressMax(int max) { - assert max > 0; - mSubCoef = max > 0 ? mSpan / max : 0; - assert mSubCoef > 0; - } - - @Override - public int getProgressMax() { - return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0; - } - - @Override - public int getProgress() { - assert mSubCoef > 0; - return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0; - } - - @Override - public void incProgress(int delta) { - if (delta > 0 && mSubCoef > 0) { - subIncProgress(delta * mSubCoef); - } - } - - @Override - public void subIncProgress(double realDelta) { - mSubValue += realDelta; - if (mParent != null) { - mParent.subIncProgress(realDelta); - } else { - mRoot.internalIncProgress(realDelta); - } - } - - @Override - public boolean displayPrompt(String title, String message) { - return mRoot.displayPrompt(title, message); - } - - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - return mRoot.displayLoginCredentialsPrompt(title, message); - } - - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mSubCoef > 0; - assert tickCount > 0; - return new ConsoleSubTaskMonitor(mRoot, - this, - mSubValue, - tickCount * mSubCoef); - } - - // --- ILogger --- - - @Override - public void error(@Nullable Throwable t, @Nullable String errorFormat, Object... args) { - mRoot.error(t, errorFormat, args); - } - - @Override - public void warning(@NonNull String warningFormat, Object... args) { - mRoot.warning(warningFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - mRoot.info(msgFormat, args); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - mRoot.verbose(msgFormat, args); - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SettingsController.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SettingsController.java deleted file mode 100644 index f0204a0a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/SettingsController.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.updater; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.utils.ILogger; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map.Entry; -import java.util.Properties; - -/** - * Controller class to get settings values. Settings are kept in-memory. - * Users of this class must first load the settings before changing them and save - * them when modified. - *

- * Settings are enumerated by constants in {@link ISettingsPage}. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class SettingsController { - - private static final String SETTINGS_FILENAME = "androidtool.cfg"; //$NON-NLS-1$ - - private final IFileOp mFileOp; - private final ILogger mSdkLog; - private final Settings mSettings; - - public interface OnChangedListener { - void onSettingsChanged(@NonNull SettingsController controller, - @NonNull Settings oldSettings); - } - private final List mChangedListeners = new ArrayList(1); - - /** The currently associated {@link ISettingsPage}. Can be null. */ - private ISettingsPage mSettingsPage; - - - /** - * Constructs a new default {@link SettingsController}. - * - * @param sdkLog A non-null logger to use. - */ - public SettingsController(@NonNull ILogger sdkLog) { - this(new LegacyFileOp(), sdkLog); - } - - /** - * Constructs a new default {@link SettingsController}. - * - * @param LegacyFileOp A non-null {@link LegacyFileOp} to perform file operations (to load/save settings.) - * @param sdkLog A non-null logger to use. - */ - public SettingsController(@NonNull IFileOp LegacyFileOp, @NonNull ILogger sdkLog) { - this(LegacyFileOp, sdkLog, new Settings()); - } - - /** - * Specialized constructor that wraps an existing {@link Settings} instance. - * This is mostly used in unit-tests to override settings that are being used. - * Normal usage should NOT need to call this constructor. - * - * @param LegacyFileOp A non-null {@link LegacyFileOp} to perform file operations (to load/save settings) - * @param sdkLog A non-null logger to use. - * @param settings A non-null {@link Settings} to use as-is. It is not duplicated. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SettingsController(@NonNull IFileOp LegacyFileOp, - @NonNull ILogger sdkLog, - @NonNull Settings settings) { - mFileOp = LegacyFileOp; - mSdkLog = sdkLog; - mSettings = settings; - } - - @NonNull - public Settings getSettings() { - return mSettings; - } - - public void registerOnChangedListener(@Nullable OnChangedListener listener) { - if (listener != null && !mChangedListeners.contains(listener)) { - mChangedListeners.add(listener); - } - } - - public void unregisterOnChangedListener(@Nullable OnChangedListener listener) { - if (listener != null) { - mChangedListeners.remove(listener); - } - } - - //--- Access to settings ------------ - - - public static class Settings { - private final Properties mProperties; - - /** Initialize an empty set of settings. */ - public Settings() { - mProperties = new Properties(); - } - - /** Duplicates a set of settings. */ - public Settings(@NonNull Settings settings) { - this(); - for (Entry entry : settings.mProperties.entrySet()) { - mProperties.put(entry.getKey(), entry.getValue()); - } - } - - /** - * Specialized constructor for unit-tests that wraps an existing - * {@link Properties} instance. The properties instance is not duplicated, - * it's merely used as-is and changes will be reflected directly. - */ - protected Settings(@NonNull Properties properties) { - mProperties = properties; - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_FORCE_HTTP} setting. - * - * @see ISettingsPage#KEY_FORCE_HTTP - */ - public boolean getForceHttp() { - return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP)); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_ASK_ADB_RESTART} setting. - * - * @see ISettingsPage#KEY_ASK_ADB_RESTART - */ - public boolean getAskBeforeAdbRestart() { - return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_ASK_ADB_RESTART)); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_USE_DOWNLOAD_CACHE} setting. - * - * @see ISettingsPage#KEY_USE_DOWNLOAD_CACHE - */ - public boolean getUseDownloadCache() { - return Boolean.parseBoolean( - mProperties.getProperty( - ISettingsPage.KEY_USE_DOWNLOAD_CACHE, - Boolean.TRUE.toString())); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. - * - * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY - */ - public boolean getShowUpdateOnly() { - return Boolean.parseBoolean( - mProperties.getProperty( - ISettingsPage.KEY_SHOW_UPDATE_ONLY, - Boolean.TRUE.toString())); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_ENABLE_PREVIEWS} setting. - * - * @see ISettingsPage#KEY_ENABLE_PREVIEWS - */ - public boolean getEnablePreviews() { - return Boolean.parseBoolean( - mProperties.getProperty( - ISettingsPage.KEY_ENABLE_PREVIEWS, - Boolean.TRUE.toString())); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting - * @see ISettingsPage#KEY_MONITOR_DENSITY - */ - public int getMonitorDensity() { - String value = mProperties.getProperty(ISettingsPage.KEY_MONITOR_DENSITY, null); - if (value == null) { - return -1; - } - - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return -1; - } - } - } - - /** - * Sets the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. - * - * @param enabled True if only compatible non-obsolete update items should be shown. - * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY - */ - public void setShowUpdateOnly(boolean enabled) { - setSetting(ISettingsPage.KEY_SHOW_UPDATE_ONLY, enabled); - } - - /** - * Sets the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting. - * - * @param density the density of the monitor - * @see ISettingsPage#KEY_MONITOR_DENSITY - */ - public void setMonitorDensity(int density) { - mSettings.mProperties.setProperty( - ISettingsPage.KEY_MONITOR_DENSITY, Integer.toString(density)); - } - - /** - * Internal helper to set a boolean setting. - */ - void setSetting(@NonNull String key, boolean value) { - mSettings.mProperties.setProperty(key, Boolean.toString(value)); - } - - //--- Controller methods ------------- - - /** - * Associate the given {@link ISettingsPage} with this {@link SettingsController}. - *

- * This loads the current properties into the setting page UI. - * It then associates the SettingsChanged callback with this controller. - *

- * If the setting page given is null, it will be unlinked from controller. - * - * @param settingsPage An {@link ISettingsPage} to associate with the controller. - */ - public void setSettingsPage(@Nullable ISettingsPage settingsPage) { - mSettingsPage = settingsPage; - - if (settingsPage != null) { - settingsPage.loadSettings(mSettings.mProperties); - - settingsPage.setOnSettingsChanged(new ISettingsPage.SettingsChangedCallback() { - @Override - public void onSettingsChanged(ISettingsPage page) { - SettingsController.this.onSettingsChanged(); - } - }); - } - } - - /** - * Load settings from the settings file. - */ - public void loadSettings() { - - String path = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - path = f.getPath(); - - Properties props = mFileOp.loadProperties(f); - mSettings.mProperties.clear(); - mSettings.mProperties.putAll(props); - - // Properly reformat some settings to enforce their default value when missing. - setShowUpdateOnly(mSettings.getShowUpdateOnly()); - setSetting(ISettingsPage.KEY_ASK_ADB_RESTART, mSettings.getAskBeforeAdbRestart()); - setSetting(ISettingsPage.KEY_USE_DOWNLOAD_CACHE, mSettings.getUseDownloadCache()); - setSetting(ISettingsPage.KEY_ENABLE_PREVIEWS, mSettings.getEnablePreviews()); - - } catch (Exception e) { - if (mSdkLog != null) { - mSdkLog.error(e, - "Failed to load settings from .android folder. Path is '%1$s'.", - path); - } - } - } - - /** - * Saves settings to the settings file. - */ - public void saveSettings() { - - String path = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - path = f.getPath(); - mFileOp.saveProperties(f, mSettings.mProperties, "## Settings for Android Tool"); //$NON-NLS-1$ - - } catch (Exception e) { - if (mSdkLog != null) { - // This is important enough that we want to really nag the user about it - String reason = null; - - if (e instanceof FileNotFoundException) { - reason = "File not found"; - } else if (e instanceof AndroidLocationException) { - reason = ".android folder not found, please define ANDROID_SDK_HOME"; - } else if (e.getMessage() != null) { - reason = String.format("%1$s: %2$s", - e.getClass().getSimpleName(), - e.getMessage()); - } else { - reason = e.getClass().getName(); - } - - mSdkLog.error(e, "Failed to save settings file '%1$s': %2$s", path, reason); - } - } - } - - /** - * When settings have changed: retrieve the new settings, apply them, save them - * and notify on-settings-changed listeners. - */ - private void onSettingsChanged() { - if (mSettingsPage == null) { - return; - } - - Settings oldSettings = new Settings(mSettings); - mSettingsPage.retrieveSettings(mSettings.mProperties); - applySettings(); - saveSettings(); - - for (OnChangedListener listener : mChangedListeners) { - try { - listener.onSettingsChanged(this, oldSettings); - } catch (Throwable ignore) {} - } - } - - /** - * Applies the current settings. - */ - public void applySettings() { - Properties props = System.getProperties(); - - // Get the configured HTTP proxy settings - String proxyHost = mSettings.mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_HOST, - ""); //$NON-NLS-1$ - String proxyPort = mSettings.mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_PORT, - ""); //$NON-NLS-1$ - - // Set both the HTTP and HTTPS proxy system properties. - // The system property constants can be found in the Java SE documentation at - // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html - final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ - - // Only change the proxy if have something in the preferences. - // Do not erase the default settings by empty values. - if (proxyHost != null && !proxyHost.isEmpty()) { - props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); - props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); - } - if (proxyPort != null && !proxyPort.isEmpty()) { - props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); - props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); - } - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/UpdaterData.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/UpdaterData.java deleted file mode 100644 index c1b691c6..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/updater/UpdaterData.java +++ /dev/null @@ -1,1336 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.repository.updater; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.AdbWrapper; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.LocalSdkParser; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.repository.License; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.internal.repository.updater.SettingsController.OnChangedListener; -import com.android.sdklib.repository.ISdkChangeListener; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.util.LineUtil; -import com.android.utils.ILogger; -import com.android.utils.IReaderLogger; -import com.android.utils.SparseIntArray; -import com.google.common.base.Charsets; -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * Data shared by the SDK Manager updaters. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class UpdaterData implements IUpdaterData { - - public static final int NO_TOOLS_MSG = 0; - public static final int TOOLS_MSG_UPDATED_FROM_ADT = 1; - public static final int TOOLS_MSG_UPDATED_FROM_SDKMAN = 2; - - private String mOsSdkRoot; - - private final LocalSdkParser mLocalSdkParser = new LocalSdkParser(); - /** Holds all sources. Do not use this directly. - * Instead use {@link #getSources()} so that unit tests can override this as needed. */ - private final SdkSources mSources = new SdkSources(); - /** Holds settings. Do not use this directly. - * Instead use {@link #getSettingsController()} so that unit tests can override this. */ - private final SettingsController mSettingsController; - private final ArrayList mListeners = new ArrayList(); - private final ILogger mSdkLog; - private ITaskFactory mTaskFactory; - - private SdkManager mSdkManager; - private AvdManager mAvdManager; - /** - * The current {@link PackageLoader} to use. - * Lazily created in {@link #getPackageLoader()}. - */ - private PackageLoader mPackageLoader; - /** - * The current {@link DownloadCache} to use. - * Lazily created in {@link #getDownloadCache()}. - */ - private DownloadCache mDownloadCache; - private AndroidLocationException mAvdManagerInitError; - - /** - * Creates a new updater data. - * - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - */ - public UpdaterData(String osSdkRoot, ILogger sdkLog) { - mOsSdkRoot = osSdkRoot; - mSdkLog = sdkLog; - - mSettingsController = initSettingsController(); - initSdk(); - } - - // ----- getters, setters ---- - - public String getOsSdkRoot() { - return mOsSdkRoot; - } - - @Override - public DownloadCache getDownloadCache() { - if (mDownloadCache == null) { - mDownloadCache = new DownloadCache( - getSettingsController().getSettings().getUseDownloadCache() ? - DownloadCache.Strategy.FRESH_CACHE : - DownloadCache.Strategy.DIRECT); - } - return mDownloadCache; - } - - public void setTaskFactory(ITaskFactory taskFactory) { - mTaskFactory = taskFactory; - } - - @Override - public ITaskFactory getTaskFactory() { - return mTaskFactory; - } - - public SdkSources getSources() { - return mSources; - } - - public LocalSdkParser getLocalSdkParser() { - return mLocalSdkParser; - } - - @Override - public ILogger getSdkLog() { - return mSdkLog; - } - - @Override - public SdkManager getSdkManager() { - return mSdkManager; - } - - @Override - public AvdManager getAvdManager() { - return mAvdManager; - } - - @Override - public SettingsController getSettingsController() { - return mSettingsController; - } - - /** Adds a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ - public void addListeners(ISdkChangeListener listener) { - if (mListeners.contains(listener) == false) { - mListeners.add(listener); - } - } - - /** Removes a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ - public void removeListener(ISdkChangeListener listener) { - mListeners.remove(listener); - } - - public PackageLoader getPackageLoader() { - // The package loader is lazily initialized here. - if (mPackageLoader == null) { - mPackageLoader = new PackageLoader(this); - } - return mPackageLoader; - } - - /** - * Check if any error occurred during initialization. - * If it did, display an error message. - * - * @return True if an error occurred, false if we should continue. - */ - public boolean checkIfInitFailed() { - if (mAvdManagerInitError != null) { - String example; - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - example = "%USERPROFILE%"; //$NON-NLS-1$ - } else { - example = "~"; //$NON-NLS-1$ - } - - String error = String.format( - "The AVD manager normally uses the user's profile directory to store " + - "AVD files. However it failed to find the default profile directory. " + - "\n" + - "To fix this, please set the environment variable ANDROID_SDK_HOME to " + - "a valid path such as \"%s\".", - example); - - displayInitError(error); - - return true; - } - return false; - } - - protected void displayInitError(String error) { - mSdkLog.error(null /* Throwable */, "%s", error); //$NON-NLS-1$ - } - - // ----- - - /** - * Runs a runnable on the UI thread. - * The base implementation just runs the runnable right away. - * - * @param r Non-null runnable. - */ - protected void runOnUiThread(@NonNull Runnable r) { - r.run(); - } - - /** - * Initializes the {@link SdkManager} and the {@link AvdManager}. - * Extracted so that we can override this in unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void initSdk() { - setSdkManager(SdkManager.createManager(mOsSdkRoot, mSdkLog)); - try { - mAvdManager = null; - mAvdManager = AvdManager.getInstance(mSdkManager.getLocalSdk(), mSdkLog); - } catch (AndroidLocationException e) { - mSdkLog.error(e, "Unable to read AVDs: " + e.getMessage()); //$NON-NLS-1$ - - // Note: we used to continue here, but the thing is that - // mAvdManager==null so nothing is really going to work as - // expected. Let's just display an error later in checkIfInitFailed() - // and abort right there. This step is just too early in the SWT - // setup process to display a message box yet. - - mAvdManagerInitError = e; - } - - // notify listeners. - broadcastOnSdkReload(); - } - - /** - * Initializes the {@link SettingsController} - * Extracted so that we can override this in unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SettingsController initSettingsController() { - SettingsController settingsController = new SettingsController(mSdkLog); - settingsController.registerOnChangedListener(new OnChangedListener() { - @Override - public void onSettingsChanged( - SettingsController controller, - SettingsController.Settings oldSettings) { - - // Reset the download cache if it doesn't match the right strategy. - // The cache instance gets lazily recreated later in getDownloadCache(). - if (mDownloadCache != null) { - if (controller.getSettings().getUseDownloadCache() && - mDownloadCache.getStrategy() != DownloadCache.Strategy.FRESH_CACHE) { - mDownloadCache = null; - } else if (!controller.getSettings().getUseDownloadCache() && - mDownloadCache.getStrategy() != DownloadCache.Strategy.DIRECT) { - mDownloadCache = null; - } - } - } - }); - return settingsController; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void setSdkManager(SdkManager sdkManager) { - mSdkManager = sdkManager; - } - - /** - * Reloads the SDK content (targets). - *

- * This also reloads the AVDs in case their status changed. - *

- * This does not notify the listeners ({@link ISdkChangeListener}). - */ - public void reloadSdk() { - // reload SDK - mSdkManager.reloadSdk(mSdkLog); - - // reload AVDs - if (mAvdManager != null) { - try { - mAvdManager.reloadAvds(mSdkLog); - } catch (AndroidLocationException e) { - // FIXME - } - } - - mLocalSdkParser.clearPackages(); - - // notify listeners - broadcastOnSdkReload(); - } - - /** - * Reloads the AVDs. - *

- * This does not notify the listeners. - */ - public void reloadAvds() { - // reload AVDs - if (mAvdManager != null) { - try { - mAvdManager.reloadAvds(mSdkLog); - } catch (AndroidLocationException e) { - mSdkLog.error(e, null); - } - } - } - - /** - * Sets up the default sources:
- * - the default google SDK repository,
- * - the user sources from prefs
- * - the extra repo URLs from the environment,
- * - and finally the extra user repo URLs from the environment. - */ - public void setupDefaultSources() { - SdkSources sources = getSources(); - - // Load the conventional sources. - // For testing, the env var can be set to replace the default root download URL. - // It must end with a / and its the location where the updater will look for - // the repository.xml, addons_list.xml and such files. - - String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (baseUrl == null || baseUrl.length() <= 0 || !baseUrl.endsWith("/")) { //$NON-NLS-1$ - baseUrl = SdkRepoConstants.URL_GOOGLE_SDK_SITE; - } - - sources.add(SdkSourceCategory.ANDROID_REPO, - new SdkRepoSource(baseUrl, - SdkSourceCategory.ANDROID_REPO.getUiName())); - - // Load user sources (this will also notify change listeners but this operation is - // done early enough that there shouldn't be any anyway.) - sources.loadUserAddons(getSdkLog()); - } - - /** - * Returns the list of installed packages, parsing them if this has not yet been done. - *

- * The package list is cached in the {@link LocalSdkParser} and will be reset when - * {@link #reloadSdk()} is invoked. - */ - public Package[] getInstalledPackages(ITaskMonitor monitor) { - LocalSdkParser parser = getLocalSdkParser(); - - Package[] packages = parser.getPackages(); - - if (packages == null) { - // load on demand the first time - packages = parser.parseSdk(getOsSdkRoot(), getSdkManager(), monitor); - } - - return packages; - } - /** - * Install the list of given {@link Archive}s. This is invoked by the user selecting some - * packages in the remote page and then clicking "install selected". - * - * @param archives The archives to install. Incompatible ones will be skipped. - * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. - * @return A list of archives that have been installed. Can be empty but not null. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected List installArchives(final List archives, final int flags) { - if (mTaskFactory == null) { - throw new IllegalArgumentException("Task Factory is null"); - } - - // this will accumulate all the packages installed. - final List newlyInstalledArchives = new ArrayList(); - - final boolean forceHttp = getSettingsController().getSettings().getForceHttp(); - - // sort all archives based on their dependency level. - Collections.sort(archives, new InstallOrderComparator()); - - mTaskFactory.start("Installing Archives", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - - final int progressPerArchive = 2 * ArchiveInstaller.NUM_MONITOR_INC; - monitor.setProgressMax(1 + archives.size() * progressPerArchive); - monitor.setDescription("Preparing to install archives"); - - boolean installedAddon = false; - boolean installedTools = false; - boolean installedPlatformTools = false; - boolean preInstallHookInvoked = false; - - // Mark all current local archives as already installed. - HashSet installedArchives = new HashSet(); - for (Package p : getInstalledPackages(monitor.createSubMonitor(1))) { - for (Archive a : p.getArchives()) { - installedArchives.add(a); - } - } - - int numInstalled = 0; - nextArchive: for (ArchiveInfo ai : archives) { - Archive archive = ai.getNewArchive(); - if (archive == null) { - // This is not supposed to happen. - continue nextArchive; - } - - int nextProgress = monitor.getProgress() + progressPerArchive; - try { - if (monitor.isCancelRequested()) { - break; - } - - ArchiveInfo[] adeps = ai.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - Archive na = adep.getNewArchive(); - if (na == null) { - // This archive depends on a missing archive. - // We shouldn't get here. - // Skip it. - monitor.log("Skipping '%1$s'; it depends on a missing package.", - archive.getParentPackage().getShortDescription()); - continue nextArchive; - } else if (!installedArchives.contains(na)) { - // This archive depends on another one that was not installed. - // We shouldn't get here. - // Skip it. - monitor.logError("Skipping '%1$s'; it depends on '%2$s' which was not installed.", - archive.getParentPackage().getShortDescription(), - adep.getShortDescription()); - continue nextArchive; - } - } - } - - if (!preInstallHookInvoked) { - preInstallHookInvoked = true; - broadcastPreInstallHook(); - } - - ArchiveInstaller installer = createArchiveInstaler(); - if (installer.install(ai, - mOsSdkRoot, - forceHttp, - mSdkManager, - getDownloadCache(), - monitor)) { - // We installed this archive. - newlyInstalledArchives.add(archive); - installedArchives.add(archive); - numInstalled++; - - // If this package was replacing an existing one, the old one - // is no longer installed. - installedArchives.remove(ai.getReplaced()); - - // Check if we successfully installed a platform-tool or add-on package. - if (archive.getParentPackage() instanceof AddonPackage) { - installedAddon = true; - } else if (archive.getParentPackage() instanceof ToolPackage) { - installedTools = true; - } else if (archive.getParentPackage() instanceof PlatformToolPackage) { - installedPlatformTools = true; - } - } - - } catch (Throwable t) { - // Display anything unexpected in the monitor. - String msg = t.getMessage(); - if (msg != null) { - msg = String.format("Unexpected Error installing '%1$s': %2$s: %3$s", - archive.getParentPackage().getShortDescription(), - t.getClass().getCanonicalName(), msg); - } else { - // no error info? get the stack call to display it - // At least that'll give us a better bug report. - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - t.printStackTrace(new PrintStream(baos)); - - msg = String.format("Unexpected Error installing '%1$s'\n%2$s", - archive.getParentPackage().getShortDescription(), - baos.toString()); - } - - monitor.log( "%1$s", msg); //$NON-NLS-1$ - mSdkLog.error(t, "%1$s", msg); //$NON-NLS-1$ - } finally { - - // Always move the progress bar to the desired position. - // This allows internal methods to not have to care in case - // they abort early - monitor.incProgress(nextProgress - monitor.getProgress()); - } - } - - if (installedAddon) { - // Update the USB vendor ids for adb - try { - mSdkManager.updateAdb(); - monitor.log("Updated ADB to support the USB devices declared in the SDK add-ons."); - } catch (Exception e) { - mSdkLog.error(e, "Update ADB failed"); - monitor.logError("failed to update adb to support the USB devices declared in the SDK add-ons."); - } - } - - if (preInstallHookInvoked) { - broadcastPostInstallHook(); - } - - if (installedAddon || installedPlatformTools) { - // We need to restart ADB. Actually since we don't know if it's even - // running, maybe we should just kill it and not start it. - // Note: it turns out even under Windows we don't need to kill adb - // before updating the tools folder, as adb.exe is (surprisingly) not - // locked. - - askForAdbRestart(monitor); - } - - if (installedTools) { - notifyToolsNeedsToBeRestarted(flags); - } - - if (numInstalled == 0) { - monitor.setDescription("Done. Nothing was installed."); - } else { - monitor.setDescription("Done. %1$d %2$s installed.", - numInstalled, - numInstalled == 1 ? "package" : "packages"); - - //notify listeners something was installed, so that they can refresh - reloadSdk(); - } - } - }); - - return newlyInstalledArchives; - } - - /** - * A comparator to sort all the {@link ArchiveInfo} based on their - * dependency level. This forces the installer to install first all packages - * with no dependency, then those with one level of dependency, etc. - */ - private static class InstallOrderComparator implements Comparator { - - private final Map mOrders = new HashMap(); - - @Override - public int compare(ArchiveInfo o1, ArchiveInfo o2) { - int n1 = getDependencyOrder(o1); - int n2 = getDependencyOrder(o2); - - return n1 - n2; - } - - private int getDependencyOrder(ArchiveInfo ai) { - if (ai == null) { - return 0; - } - - // reuse cached value, if any - Integer cached = mOrders.get(ai); - if (cached != null) { - return cached.intValue(); - } - - ArchiveInfo[] deps = ai.getDependsOn(); - if (deps == null) { - return 0; - } - - // compute dependencies, recursively - int n = deps.length; - - for (ArchiveInfo dep : deps) { - n += getDependencyOrder(dep); - } - - // cache it - mOrders.put(ai, Integer.valueOf(n)); - - return n; - } - - } - - /** - * Attempts to restart ADB. - *

- * If the "ask before restart" setting is set (the default), prompt the user whether - * now is a good time to restart ADB. - */ - protected void askForAdbRestart(ITaskMonitor monitor) { - // Restart ADB if we don't need to ask. - if (!getSettingsController().getSettings().getAskBeforeAdbRestart()) { - AdbWrapper adb = new AdbWrapper(getOsSdkRoot(), monitor); - adb.stopAdb(); - adb.startAdb(); - } - } - - protected void notifyToolsNeedsToBeRestarted(int flags) { - - String msg = null; - if ((flags & TOOLS_MSG_UPDATED_FROM_ADT) == TOOLS_MSG_UPDATED_FROM_ADT) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "Please also run Eclipse > Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - - } else if ((flags & TOOLS_MSG_UPDATED_FROM_SDKMAN) == TOOLS_MSG_UPDATED_FROM_SDKMAN) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "It is recommended that you now close the manager window and re-open it. " + - "If you use Eclipse, please run Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - } else if ((flags & NO_TOOLS_MSG) == NO_TOOLS_MSG) { - return; - } - mSdkLog.info("%s", msg); //$NON-NLS-1$ - } - - /** - * Fetches all archives available on the known remote sources. - * - * Used by {@link UpdaterData#listRemotePackages_NoGUI} and - * {@link UpdaterData#updateOrInstallAll_NoGUI}. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @return A list of potential {@link ArchiveInfo} to install. - */ - private List getRemoteArchives_NoGUI(boolean includeAll) { - refreshSources(true); - getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog())); - - List archives; - SdkUpdaterLogic ul = new SdkUpdaterLogic(this); - - if (includeAll) { - archives = ul.getAllRemoteArchives( - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - - } else { - archives = ul.computeUpdates( - null /*selectedArchives*/, - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - - ul.addNewPlatforms( - archives, - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - } - - Collections.sort(archives); - return archives; - } - - /** - * Lists remote packages available for install using - * {@link UpdaterData#updateOrInstallAll_NoGUI}. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @param extendedOutput True to display more details on each package. - */ - public void listRemotePackages_NoGUI(boolean includeAll, boolean extendedOutput) { - - List archives = getRemoteArchives_NoGUI(includeAll); - - mSdkLog.info("Packages available for installation or update: %1$d\n", archives.size()); - - int index = 1; - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - if (extendedOutput) { - mSdkLog.info("----------\n"); - mSdkLog.info("id: %1$d or \"%2$s\"\n", index, p.installId()); - mSdkLog.info(" Type: %1$s\n", - p.getClass().getSimpleName().replaceAll("Package", "")); //$NON-NLS-1$ //$NON-NLS-2$ - String desc = LineUtil.reformatLine(" Desc: %s\n", - p.getLongDescription()); - mSdkLog.info("%s", desc); //$NON-NLS-1$ - } else { - mSdkLog.info("%1$ 4d- %2$s\n", - index, - p.getShortDescription()); - } - index++; - } - } - } - } - - /** - * Tries to update all the *existing* local packages. - * This version *requires* to be run with a GUI. - *

- * There are two modes of operation: - *

    - *
  • If selectedArchives is null, refreshes all sources, compares the available remote - * packages with the current local ones and suggest updates to be done to the user (including - * new platforms that the users doesn't have yet). - *
  • If selectedArchives is not null, this represents a list of archives/packages that - * the user wants to install or update, so just process these. - *
- * - * @param selectedArchives The list of remote archives to consider for the update. - * This can be null, in which case a list of remote archive is fetched from all - * available sources. - * @param includeObsoletes True if obsolete packages should be used when resolving what - * to update. - * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. - * @return A list of archives that have been installed. Can be null if nothing was done. - */ - public List updateOrInstallAll_WithGUI( - Collection selectedArchives, - boolean includeObsoletes, - int flags) { - // FIXME revisit this logic. This is just an transitional implementation - // while I refactor the way the sdk manager works internally. - - SdkUpdaterLogic ul = new SdkUpdaterLogic(this); - List archives = ul.computeUpdates( - selectedArchives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - - if (selectedArchives == null) { - getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog())); - ul.addNewPlatforms( - archives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - } - - Collections.sort(archives); - - if (!archives.isEmpty()) { - return installArchives(archives, flags); - } - return null; - } - - /** - * Tries to update all the *existing* local packages. - * This version is intended to run without a GUI and - * only outputs to the current {@link ILogger}. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()} - * or package indexes to limit the packages we can update or install. - * A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - * @param acceptLicense SDK licenses to automatically accept. - * @return A list of archives that have been installed. Can be null if nothing was done. - * @deprecated Use {@link #updateOrInstallAll_NoGUI(java.util.Collection, boolean, boolean, String, boolean)} - * instead - */ - @Deprecated - public List updateOrInstallAll_NoGUI( - Collection pkgFilter, - boolean includeAll, - boolean dryMode, - String acceptLicense) { - return updateOrInstallAll_NoGUI(pkgFilter, includeAll, dryMode, acceptLicense, false); - } - - /** - * Tries to update all the *existing* local packages. - * This version is intended to run without a GUI and - * only outputs to the current {@link ILogger}. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()} - * or package indexes to limit the packages we can update or install. - * A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - * @param acceptLicense SDK licenses to automatically accept. - * @param includeDependencies If true, also include any required dependencies - * @return A list of archives that have been installed. Can be null if nothing was done. - */ - public List updateOrInstallAll_NoGUI( - Collection pkgFilter, - boolean includeAll, - boolean dryMode, - String acceptLicense, - boolean includeDependencies) { - - List archives = getRemoteArchives_NoGUI(includeAll); - - // Filter the selected archives to only keep the ones matching the filter - if (pkgFilter != null && !pkgFilter.isEmpty() && archives != null && !archives.isEmpty()) { - // Map filter types to an SdkRepository Package type, - // e.g. create a map "platform" => PlatformPackage.class - HashMap> pkgMap = - new HashMap>(); - - mapFilterToPackageClass(pkgMap, SdkRepoConstants.NODES); - mapFilterToPackageClass(pkgMap, SdkAddonConstants.NODES); - - // Prepare a map install-id => package instance - HashMap installIdMap = new HashMap(); - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - String iid = p.installId().toLowerCase(Locale.US); - if (iid != null && !iid.isEmpty() && !installIdMap.containsKey(iid)) { - installIdMap.put(iid, p); - } - } - } - } - - // Now intersect this with the pkgFilter requested by the user, in order to - // only keep the classes that the user wants to install. - // We also create a set with the package indices requested by the user - // and a set of install-ids requested by the user. - - HashSet> userFilteredClasses = - new HashSet>(); - SparseIntArray userFilteredIndices = new SparseIntArray(); - Set userFilteredInstallIds = new HashSet(); - - for (String iid : pkgFilter) { - // The install-id is not case-sensitive. - iid = iid.toLowerCase(Locale.US); - - if (installIdMap.containsKey(iid)) { - userFilteredInstallIds.add(iid); - - } else if (iid.replaceAll("[0-9]+", "").isEmpty()) {//$NON-NLS-1$ //$NON-NLS-2$ - // An all-digit number is a package index requested by the user. - int index = Integer.parseInt(iid); - userFilteredIndices.put(index, index); - - } else if (pkgMap.containsKey(iid)) { - userFilteredClasses.add(pkgMap.get(iid)); - - } else { - // This should not happen unless there's a mismatch in the package map. - mSdkLog.error(null, "Ignoring unknown package filter '%1$s'", iid); - } - } - - // we don't need the maps anymore - pkgMap = null; - installIdMap = null; - - // Now filter the remote archives list to keep: - // - any package which class matches userFilteredClasses - // - any package index which matches userFilteredIndices - // - any package install id which matches userFilteredInstallIds - - int index = 1; - for (Iterator it = archives.iterator(); it.hasNext(); ) { - boolean keep = false; - ArchiveInfo ai = it.next(); - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - if (userFilteredInstallIds.contains(p.installId().toLowerCase(Locale.US)) || - userFilteredClasses.contains(p.getClass()) || - userFilteredIndices.get(index) > 0) { - keep = true; - } - - index++; - } - } - - if (!keep) { - it.remove(); - } - } - - if (archives.isEmpty()) { - mSdkLog.info(LineUtil.reflowLine( - "Warning: The package filter removed all packages. There is nothing to install.\nPlease consider trying to update again without a package filter.\n")); - return null; - } - } - - if (archives != null && !archives.isEmpty()) { - if (includeDependencies) { - List dependencies = getDependencies(archives); - if (!dependencies.isEmpty()) { - List combined = Lists.newArrayList(); - combined.addAll(dependencies); - combined.addAll(archives); - archives = combined; - } - } - if (dryMode) { - mSdkLog.info("Packages selected for install:\n"); - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - mSdkLog.info("- %1$s\n", p.getShortDescription()); - } - } - } - mSdkLog.info("\nDry mode is on so nothing is actually being installed.\n"); - } else { - if (acceptLicense(archives, acceptLicense, 100 /* numRetries */)) { - return installArchives(archives, NO_TOOLS_MSG); - } - } - } else { - mSdkLog.info("There is nothing to install or update.\n"); - } - - return null; - } - - /** - * Computes the transitive dependencies of the given list of archives. This will only - * include dependencies that also need to be installed, not satisfied dependencies. - */ - private static List getDependencies(@NonNull List archives) { - List dependencies = Lists.newArrayList(); - for (ArchiveInfo archive : archives) { - addDependencies(dependencies, archive, Sets.newHashSet()); - } - return dependencies; - } - - private static void addDependencies(@NonNull List dependencies, - @NonNull ArchiveInfo archive, - @NonNull Set visited) { - if (visited.contains(archive)) { - return; - } - visited.add(archive); - - ArchiveInfo[] dependsOn = archive.getDependsOn(); - if (dependsOn != null) { - for (ArchiveInfo dependency : dependsOn) { - if (!dependencies.contains(dependency)) { - dependencies.add(dependency); - addDependencies(dependencies, dependency, visited); - } - } - } - } - - /** - * Validates that all archive licenses are accepted. - *

- * There are 2 cases:
- * - When {@code acceptLicenses} is given, the licenses specified are automatically - * accepted and all those not specified are automatically rejected.
- * - When {@code acceptLicenses} is empty or null, licenses are collected and there's - * an input prompt on StdOut to ask a yes/no question. To output, this uses the - * current {@link #mSdkLog} which should be configured to send - * {@link ILogger#info(String, Object...)} directly to {@link System#out}.
- * - * Finally only accepted licenses are kept in the archive list. - * - * @param archives The archives to validate. - * @param acceptLicenseIds A comma-separated list of licenses ids already approved. - * @param numRetries The number of times the command-line will ask to accept a given - * license when the input doesn't match the expected y/n/yes/no answer. - * Use 0 for infinite. Useful for unit-tests. Once the number of retries - * is reached, the license is assumed as rejected. - * @return True if there are any archives left to install. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - boolean acceptLicense( - List archives, - String acceptLicenseIds, - final int numRetries) { - TreeSet acceptedLids = new TreeSet(); - if (acceptLicenseIds != null) { - acceptedLids.addAll(Arrays.asList(acceptLicenseIds.split(","))); //$NON-NLS-1$ - } - boolean automated = !acceptedLids.isEmpty(); - - TreeSet rejectedLids = new TreeSet(); - TreeMap lidToAccept = new TreeMap(); - TreeMap> lidPkgNames = new TreeMap>(); - - // Find the licenses needed. Include those already accepted. - for (ArchiveInfo ai : archives) { - License lic = getArchiveInfoLicense(ai); - if (lic == null) { - continue; - } - String lid = getLicenseId(lic); - if (!acceptedLids.contains(lid)) { - if (automated) { - // Automatically reject those not already accepted - rejectedLids.add(lid); - } else { - // Queue it to ask for it to be accepted - lidToAccept.put(lid, lic); - List list = lidPkgNames.get(lid); - if (list == null) { - list = new ArrayList(); - lidPkgNames.put(lid, list); - } - list.add(ai.getShortDescription()); - } - } - } - - // Ask for each license that needs to be asked manually for confirmation - nextEntry: for (Map.Entry entry : lidToAccept.entrySet()) { - String lid = entry.getKey(); - License lic = entry.getValue(); - mSdkLog.info("-------------------------------\n"); - mSdkLog.info("License id: %1$s\n", lid); - mSdkLog.info("Used by: \n - %1$s\n", - Joiner.on("\n - ").skipNulls().join(lidPkgNames.get(lid))); - mSdkLog.info("-------------------------------\n\n"); - mSdkLog.info("%1$s\n", lic.getLicense()); - - int retries = numRetries; - tryAgain: while(true) { - try { - mSdkLog.info("Do you accept the license '%1$s' [y/n]: ", lid); - - byte[] buffer = new byte[256]; - if (mSdkLog instanceof IReaderLogger) { - ((IReaderLogger) mSdkLog).readLine(buffer); - } else { - System.in.read(buffer); - } - mSdkLog.info("\n"); - - String reply = new String(buffer, Charsets.UTF_8); - reply = reply.trim().toLowerCase(Locale.US); - - if ("y".equals(reply) || "yes".equals(reply)) { - acceptedLids.add(lid); - continue nextEntry; - - } else if ("n".equals(reply) || "no".equals(reply)) { - break tryAgain; - - } else { - mSdkLog.info("Unknown response '%1$s'.\n", reply); - if (--retries == 0) { - mSdkLog.info("Max number of retries exceeded. Rejecting '%1$s'\n", lid); - break tryAgain; - } - continue tryAgain; - } - - } catch (IOException e) { - // Panic. Don't install anything. - e.printStackTrace(); - return false; - } - } - rejectedLids.add(lid); - } - - // Finally remove all archive which license is rejected or not accepted. - for (Iterator it = archives.iterator(); it.hasNext(); ) { - ArchiveInfo ai = it.next(); - License lic = getArchiveInfoLicense(ai); - if (lic == null) { - continue; - } - String lid = getLicenseId(lic); - if (rejectedLids.contains(lid) || !acceptedLids.contains(lid)) { - mSdkLog.info("Package %1$s not installed due to rejected license '%2$s'.\n", - ai.getShortDescription(), - lid); - it.remove(); - } - } - - - return !archives.isEmpty(); - } - - private License getArchiveInfoLicense(ArchiveInfo ai) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - License lic = p.getLicense(); - if (lic != null && - lic.getLicenseRef() != null && - !lic.getLicense().isEmpty() && - lic.getLicense() != null && - !lic.getLicense().isEmpty()) { - return lic; - } - } - } - - return null; - } - - private String getLicenseId(License lic) { - return String.format("%1$s-%2$08x", //$NON-NLS-1$ - lic.getLicenseRef(), - lic.getLicense().hashCode()); - } - - @SuppressWarnings("unchecked") - private void mapFilterToPackageClass( - HashMap> inOutPkgMap, - String[] nodes) { - - // Automatically find the classes matching the node names - ClassLoader classLoader = getClass().getClassLoader(); - String basePackage = Package.class.getPackage().getName(); - - for (String node : nodes) { - // Capitalize the name - String name = node.substring(0, 1).toUpperCase() + node.substring(1); - - // We can have one dash at most in a name. If it's present, we'll try - // with the dash or with the next letter capitalized. - int dash = name.indexOf('-'); - if (dash > 0) { - name = name.replaceFirst("-", ""); - } - - for (int alternatives = 0; alternatives < 2; alternatives++) { - - String fqcn = basePackage + '.' + name + "Package"; //$NON-NLS-1$ - try { - Class clazz = - (Class) classLoader.loadClass(fqcn); - if (clazz != null) { - inOutPkgMap.put(node, clazz); - continue; - } - } catch (Throwable ignore) { - } - - if (alternatives == 0 && dash > 0) { - // Try an alternative where the next letter after the dash - // is converted to an upper case. - name = name.substring(0, dash) + - name.substring(dash, dash + 1).toUpperCase() + - name.substring(dash + 1); - } else { - break; - } - } - } - } - - /** - * Refresh all sources. This is invoked either internally (reusing an existing monitor) - * or as a UI callback on the remote page "Refresh" button (in which case the monitor is - * null and a new task should be created.) - * - * @param forceFetching When true, load sources that haven't been loaded yet. - * When false, only refresh sources that have been loaded yet. - */ - public void refreshSources(final boolean forceFetching) { - assert mTaskFactory != null; - - final boolean forceHttp = getSettingsController().getSettings().getForceHttp(); - - mTaskFactory.start("Refresh Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - - getPackageLoader().loadRemoteAddonsList(monitor); - - SdkSource[] sources = getSources().getAllSources(); - monitor.setDescription("Refresh Sources"); - monitor.setProgressMax(monitor.getProgress() + sources.length); - for (SdkSource source : sources) { - if (forceFetching || - source.getPackages() != null || - source.getFetchError() != null) { - source.load(getDownloadCache(), monitor.createSubMonitor(1), forceHttp); - } - monitor.incProgress(1); - } - } - }); - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#onSdkLoaded()}. - * This can be called from any thread. - */ - public void broadcastOnSdkLoaded() { - if (!mListeners.isEmpty()) { - runOnUiThread(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.onSdkLoaded(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#onSdkReload()}. - * This can be called from any thread. - */ - private void broadcastOnSdkReload() { - if (!mListeners.isEmpty()) { - runOnUiThread(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.onSdkReload(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#preInstallHook()}. - * This can be called from any thread. - */ - private void broadcastPreInstallHook() { - if (!mListeners.isEmpty()) { - runOnUiThread(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.preInstallHook(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#postInstallHook()}. - * This can be called from any thread. - */ - private void broadcastPostInstallHook() { - if (!mListeners.isEmpty()) { - runOnUiThread(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.postInstallHook(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Internal helper to return a new {@link ArchiveInstaller}. - * This allows us to override the installer for unit-testing. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected ArchiveInstaller createArchiveInstaler() { - return new ArchiveInstaller(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/IFileOp.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/IFileOp.java deleted file mode 100644 index 4ed4ab1c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/IFileOp.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2011 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.io; - -import com.android.annotations.NonNull; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Properties; - - -/** - * Wraps some common {@link File} operations on files and folders. - *

- * This makes it possible to override/mock/stub some file operations in unit tests. - */ -public interface IFileOp { - - /** - * Helper to delete a file or a directory. - * For a directory, recursively deletes all of its content. - * Files that cannot be deleted right away are marked for deletion on exit. - * It's ok for the file or folder to not exist at all. - * The argument can be null. - */ - void deleteFileOrFolder(@NonNull File fileOrFolder); - - /** - * Sets the executable Unix permission (+x) on a file or folder. - *

- * This attempts to use File#setExecutable through reflection if - * it's available. - * If this is not available, this invokes a chmod exec instead, - * so there is no guarantee of it being fast. - *

- * Caller must make sure to not invoke this under Windows. - * - * @param file The file to set permissions on. - * @throws IOException If an I/O error occurs - */ - void setExecutablePermission(@NonNull File file) throws IOException; - - /** - * Sets the file or directory as read-only. - * - * @param file The file or directory to set permissions on. - */ - void setReadOnly(@NonNull File file); - - /** - * Copies a binary file. - * - * @param source the source file to copy. - * @param dest the destination file to write. - * @throws FileNotFoundException if the source file doesn't exist. - * @throws IOException if there's a problem reading or writing the file. - */ - void copyFile(@NonNull File source, @NonNull File dest) throws IOException; - - /** - * Checks whether 2 binary files are the same. - * - * @param file1 the source file to copy - * @param file2 the destination file to write - * @throws FileNotFoundException if the source files don't exist. - * @throws IOException if there's a problem reading the files. - */ - boolean isSameFile(@NonNull File file1, @NonNull File file2) - throws IOException; - - /** Invokes {@link File#exists()} on the given {@code file}. */ - boolean exists(@NonNull File file); - - /** Invokes {@link File#isFile()} on the given {@code file}. */ - boolean isFile(@NonNull File file); - - /** Invokes {@link File#isDirectory()} on the given {@code file}. */ - boolean isDirectory(@NonNull File file); - - /** Invokes {@link File#length()} on the given {@code file}. */ - long length(@NonNull File file); - - /** - * Invokes {@link File#delete()} on the given {@code file}. - * Note: for a recursive folder version, consider {@link #deleteFileOrFolder(File)}. - */ - boolean delete(@NonNull File file); - - /** Invokes {@link File#mkdirs()} on the given {@code file}. */ - boolean mkdirs(@NonNull File file); - - /** - * Invokes {@link File#listFiles()} on the given {@code file}. - * Contrary to the Java API, this returns an empty array instead of null when the - * directory does not exist. - */ - @NonNull - File[] listFiles(@NonNull File file); - - /** Invokes {@link File#renameTo(File)} on the given files. */ - boolean renameTo(@NonNull File oldDir, @NonNull File newDir); - - /** Creates a new {@link OutputStream} for the given {@code file}. */ - @NonNull - OutputStream newFileOutputStream(@NonNull File file) - throws FileNotFoundException; - - /** Creates a new {@link InputStream} for the given {@code file}. */ - @NonNull - InputStream newFileInputStream(@NonNull File file) - throws FileNotFoundException; - - /** - * Load {@link Properties} from a file. Returns an empty property set on error. - * - * @param file A non-null file to load from. File may not exist. - * @return A new {@link Properties} with the properties loaded from the file, - * or an empty property set in case of error. - */ - @NonNull - Properties loadProperties(@NonNull File file); - - /** - * Saves (write, store) the given {@link Properties} into the given {@link File}. - * - * @param file A non-null file to write to. - * @param props The properties to write. - * @param comments A non-null description of the properly list, written in the file. - * @throws IOException if the write operation failed. - */ - void saveProperties( - @NonNull File file, - @NonNull Properties props, - @NonNull String comments) throws IOException; - - /** - * Returns the lastModified attribute of the file. - * - * @see File#lastModified() - * @param file The non-null file of which to retrieve the lastModified attribute. - * @return The last-modified attribute of the file, in milliseconds since The Epoch. - */ - long lastModified(@NonNull File file); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/LegacyFileOp.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/LegacyFileOp.java deleted file mode 100644 index 95b9ff72..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/io/LegacyFileOp.java +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (C) 2010 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.io; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.google.common.io.Closer; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Properties; -import java.util.regex.Pattern; - - -/** - * Wraps some common {@link File} operations on files and folders. - *

- * This makes it possible to override/mock/stub some file operations in unit tests. - */ -public class LegacyFileOp implements IFileOp { - - public static final File[] EMPTY_FILE_ARRAY = new File[0]; - - /** - * Reflection method for File.setExecutable(boolean, boolean). Only present in Java 6. - */ - private static Method sFileSetExecutable = null; - - /** - * Parameters to call File.setExecutable through reflection. - */ - private static final Object[] sFileSetExecutableParams = new Object[] { - Boolean.TRUE, Boolean.FALSE }; - - // static initialization of sFileSetExecutable. - static { - try { - sFileSetExecutable = File.class.getMethod("setExecutable", //$NON-NLS-1$ - boolean.class, boolean.class); - - } catch (SecurityException e) { - // do nothing we'll use chmod instead - } catch (NoSuchMethodException e) { - // do nothing we'll use chmod instead - } - } - - /** - * Appends the given {@code segments} to the {@code base} file. - * - * @param base A base file, non-null. - * @param segments Individual folder or filename segments to append to the base file. - * @return A new file representing the concatenation of the base path with all the segments. - */ - public static File append(@NonNull File base, @NonNull String...segments) { - for (String segment : segments) { - base = new File(base, segment); - } - return base; - } - - /** - * Appends the given {@code segments} to the {@code base} file. - * - * @param base A base file path, non-empty and non-null. - * @param segments Individual folder or filename segments to append to the base path. - * @return A new file representing the concatenation of the base path with all the segments. - */ - public static File append(@NonNull String base, @NonNull String...segments) { - return append(new File(base), segments); - } - - /** - * Helper to delete a file or a directory. - * For a directory, recursively deletes all of its content. - * Files that cannot be deleted right away are marked for deletion on exit. - * It's ok for the file or folder to not exist at all. - * The argument can be null. - */ - @Override - public void deleteFileOrFolder(@NonNull File fileOrFolder) { - if (fileOrFolder != null) { - if (isDirectory(fileOrFolder)) { - // Must delete content recursively first - File[] files = fileOrFolder.listFiles(); - if (files != null) { - for (File item : files) { - deleteFileOrFolder(item); - } - } - } - - // Don't try to delete it if it doesn't exist. - if (!exists(fileOrFolder)) { - return; - } - - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) { - // Trying to delete a resource on windows might fail if there's a file - // indexer locking the resource. Generally retrying will be enough to - // make it work. - // - // Try for half a second before giving up. - - for (int i = 0; i < 5; i++) { - if (fileOrFolder.delete()) { - return; - } - - try { - Thread.sleep(100 /*ms*/); - } catch (InterruptedException e) { - // Ignore. - } - } - - fileOrFolder.deleteOnExit(); - - } else { - // On Linux or Mac, just straight deleting it should just work. - - if (!fileOrFolder.delete()) { - fileOrFolder.deleteOnExit(); - } - } - } - } - - /** - * Sets the executable Unix permission (+x) on a file or folder. - *

- * This attempts to use File#setExecutable through reflection if - * it's available. - * If this is not available, this invokes a chmod exec instead, - * so there is no guarantee of it being fast. - *

- * Caller must make sure to not invoke this under Windows. - * - * @param file The file to set permissions on. - * @throws IOException If an I/O error occurs - */ - @Override - public void setExecutablePermission(@NonNull File file) throws IOException { - - if (sFileSetExecutable != null) { - try { - sFileSetExecutable.invoke(file, sFileSetExecutableParams); - return; - } catch (IllegalArgumentException e) { - // we'll run chmod below - } catch (IllegalAccessException e) { - // we'll run chmod below - } catch (InvocationTargetException e) { - // we'll run chmod below - } - } - - Runtime.getRuntime().exec(new String[] { - "chmod", "+x", file.getAbsolutePath() //$NON-NLS-1$ //$NON-NLS-2$ - }); - } - - @Override - public void setReadOnly(@NonNull File file) { - file.setReadOnly(); - } - - /** - * Copies a binary file. - * - * @param source the source file to copy. - * @param dest the destination file to write. - * @throws FileNotFoundException if the source file doesn't exist. - * @throws IOException if there's a problem reading or writing the file. - */ - @Override - public void copyFile(@NonNull File source, @NonNull File dest) throws IOException { - byte[] buffer = new byte[8192]; - - FileInputStream fis = null; - FileOutputStream fos = null; - try { - fis = new FileInputStream(source); - fos = new FileOutputStream(dest); - - int read; - while ((read = fis.read(buffer)) != -1) { - fos.write(buffer, 0, read); - } - - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - // Ignore. - } - } - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - // Ignore. - } - } - } - } - - /** - * Checks whether 2 binary files are the same. - * - * @param file1 the source file to copy - * @param file2 the destination file to write - * @throws FileNotFoundException if the source files don't exist. - * @throws IOException if there's a problem reading the files. - */ - @Override - public boolean isSameFile(@NonNull File file1, @NonNull File file2) throws IOException { - - if (file1.length() != file2.length()) { - return false; - } - - FileInputStream fis1 = null; - FileInputStream fis2 = null; - - try { - fis1 = new FileInputStream(file1); - fis2 = new FileInputStream(file2); - - byte[] buffer1 = new byte[8192]; - byte[] buffer2 = new byte[8192]; - - int read1; - while ((read1 = fis1.read(buffer1)) != -1) { - int read2 = 0; - while (read2 < read1) { - int n = fis2.read(buffer2, read2, read1 - read2); - if (n == -1) { - break; - } - } - - if (read2 != read1) { - return false; - } - - if (!Arrays.equals(buffer1, buffer2)) { - return false; - } - } - } finally { - if (fis2 != null) { - try { - fis2.close(); - } catch (IOException e) { - // ignore - } - } - if (fis1 != null) { - try { - fis1.close(); - } catch (IOException e) { - // ignore - } - } - } - - return true; - } - - /** Invokes {@link File#isFile()} on the given {@code file}. */ - @Override - public boolean isFile(@NonNull File file) { - return file.isFile(); - } - - /** Invokes {@link File#isDirectory()} on the given {@code file}. */ - @Override - public boolean isDirectory(@NonNull File file) { - return file.isDirectory(); - } - - /** Invokes {@link File#exists()} on the given {@code file}. */ - @Override - public boolean exists(@NonNull File file) { - return file.exists(); - } - - /** Invokes {@link File#length()} on the given {@code file}. */ - @Override - public long length(@NonNull File file) { - return file.length(); - } - - /** - * Invokes {@link File#delete()} on the given {@code file}. - * Note: for a recursive folder version, consider {@link #deleteFileOrFolder(File)}. - */ - @Override - public boolean delete(@NonNull File file) { - return file.delete(); - } - - /** Invokes {@link File#mkdirs()} on the given {@code file}. */ - @Override - public boolean mkdirs(@NonNull File file) { - return file.mkdirs(); - } - - /** - * Invokes {@link File#listFiles()} on the given {@code file}. - * Contrary to the Java API, this returns an empty array instead of null when the - * directory does not exist. - */ - @Override - @NonNull - public File[] listFiles(@NonNull File file) { - File[] r = file.listFiles(); - if (r == null) { - return EMPTY_FILE_ARRAY; - } else { - return r; - } - } - - /** Invokes {@link File#renameTo(File)} on the given files. */ - @Override - public boolean renameTo(@NonNull File oldFile, @NonNull File newFile) { - return oldFile.renameTo(newFile); - } - - /** Creates a new {@link OutputStream} for the given {@code file}. */ - @Override - @NonNull - public OutputStream newFileOutputStream(@NonNull File file) throws FileNotFoundException { - return new FileOutputStream(file); - } - - /** Creates a new {@link InputStream} for the given {@code file}. */ - @Override - @NonNull - public InputStream newFileInputStream(@NonNull File file) throws FileNotFoundException { - return new FileInputStream(file); - } - - @Override - @NonNull - public Properties loadProperties(@NonNull File file) { - Properties props = new Properties(); - Closer closer = Closer.create(); - try { - FileInputStream fis = closer.register(new FileInputStream(file)); - props.load(fis); - } catch (IOException ignore) { - } finally { - try { - closer.close(); - } catch (IOException e) { - } - } - return props; - } - - @Override - public void saveProperties( - @NonNull File file, - @NonNull Properties props, - @NonNull String comments) throws IOException { - Closer closer = Closer.create(); - try { - OutputStream fos = closer.register(newFileOutputStream(file)); - props.store(fos, comments); - } catch (Throwable e) { - throw closer.rethrow(e); - } finally { - closer.close(); - } - } - - @Override - public long lastModified(@NonNull File file) { - return file.lastModified(); - } - - /** - * Computes a relative path from "toBeRelative" relative to "baseDir". - * - * Rule: - * - let relative2 = makeRelative(path1, path2) - * - then pathJoin(path1 + relative2) == path2 after canonicalization. - * - * Principle: - * - let base = /c1/c2.../cN/a1/a2../aN - * - let toBeRelative = /c1/c2.../cN/b1/b2../bN - * - result is removes the common paths, goes back from aN to cN then to bN: - * - result = ../..../../1/b2../bN - * - * @param baseDir The base directory to be relative to. - * @param toBeRelative The file or directory to make relative to the base. - * @return A path that makes toBeRelative relative to baseDir. - * @throws IOException If drive letters don't match on Windows or path canonicalization fails. - */ - @NonNull - public static String makeRelative(@NonNull File baseDir, @NonNull File toBeRelative) - throws IOException { - return makeRelativeImpl( - baseDir.getCanonicalPath(), - toBeRelative.getCanonicalPath(), - SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS, - File.separator); - } - - /** - * Implementation detail of makeRelative to make it testable - * Independently of the platform. - */ - @NonNull - static String makeRelativeImpl(@NonNull String path1, - @NonNull String path2, - boolean isWindows, - @NonNull String dirSeparator) - throws IOException { - if (isWindows) { - // Check whether both path are on the same drive letter, if any. - String p1 = path1; - String p2 = path2; - char drive1 = (p1.length() >= 2 && p1.charAt(1) == ':') ? p1.charAt(0) : 0; - char drive2 = (p2.length() >= 2 && p2.charAt(1) == ':') ? p2.charAt(0) : 0; - if (drive1 != drive2) { - // Either a mix of UNC vs drive or not the same drives. - throw new IOException("makeRelative: incompatible drive letters"); - } - } - - String[] segments1 = path1.split(Pattern.quote(dirSeparator)); - String[] segments2 = path2.split(Pattern.quote(dirSeparator)); - - int len1 = segments1.length; - int len2 = segments2.length; - int len = Math.min(len1, len2); - int start = 0; - for (; start < len; start++) { - // On Windows should compare in case-insensitive. - // Mac & Linux file systems can be both type, although their default - // is generally to have a case-sensitive file system. - if (( isWindows && !segments1[start].equalsIgnoreCase(segments2[start])) || - (!isWindows && !segments1[start].equals(segments2[start]))) { - break; - } - } - - StringBuilder result = new StringBuilder(); - for (int i = start; i < len1; i++) { - result.append("..").append(dirSeparator); - } - while (start < len2) { - result.append(segments2[start]); - if (++start < len2) { - result.append(dirSeparator); - } - } - - return result.toString(); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/AddonManifestIniProps.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/AddonManifestIniProps.java deleted file mode 100644 index de82b2e8..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/AddonManifestIniProps.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2014 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.sdklib.repository; - -/** - * This class describes the properties that can appear in an add-on's manifest.ini file. - *

- * These constants are public and part of the SDK Manager public API. - * Once published we can't change them arbitrarily since various parts - * of our build process depend on them. - */ -public class AddonManifestIniProps { - - /** - * The display name of the add-on. Always present.
- * In source.properties, this matches {@link PkgProps#ADDON_NAME_DISPLAY}. - */ - public static final String ADDON_NAME = "name"; //$NON-NLS-1$ - - /** - * The optional "name id" of the add-on.
- * In source.properties, this matches {@link PkgProps#ADDON_NAME_ID}. - *

- * Historically the manifest used to have only a 'name' property for both internal unique id - * and display, in which case the internal id was synthesized using the display name and - * matching a {@code [a-zA-Z0-9_-]+} pattern (see {@code Addonpackage#sanitizeDisplayToNameId} - * for details.) - */ - public static final String ADDON_NAME_ID = "name-id"; //$NON-NLS-1$ - - /** - * The display vendor of the add-on. Always present.
- * In source.properties, this matches {@link PkgProps#ADDON_VENDOR_DISPLAY}. - */ - public static final String ADDON_VENDOR = "vendor"; //$NON-NLS-1$ - - /** - * The optional vendor id of the add-on.
- * In source.properties, this matches {@link PkgProps#ADDON_VENDOR_ID}. - *

- * Historically the manifest used to have only a 'vendor' property for both internal unique id - * and display, in which case the internal id was synthesized using the display name and - * matching a {@code [a-zA-Z0-9_-]+} pattern (see {@code Addonpackage#sanitizeDisplayToNameId} - * for details.) - */ - public static final String ADDON_VENDOR_ID = "vendor-id"; //$NON-NLS-1$ - - /** - * The free description string of the add-on.
- * Not saved in source.properties. - */ - public static final String ADDON_DESCRIPTION = "description"; //$NON-NLS-1$ - - /** - * The revision of the add-on.
- * In source.properties, this matches {@link PkgProps#PKG_REVISION}. - */ - public static final String ADDON_REVISION = "revision"; //$NON-NLS-1$ - - /** - * An older/obsolete attribute for the revision of the add-on.
- * The name was changed as it is ambiguous (platform version vs platform revision.) - */ - public static final String ADDON_REVISION_OLD = "version"; //$NON-NLS-1$ - - /** - * The API level of the add-on, always an integer.
- * Note: add-ons do not currently support API codenames.
- * In source.properties, this matches {@link PkgProps#VERSION_API_LEVEL}. - */ - public static final String ADDON_API = "api"; //$NON-NLS-1$ - - /** - * The list of libraries of the add-on.
- * This is a string in the format "java.package1;java.package2;...java.packageN". - * For each library's java package name, the manifest.ini contains a key with - * value "library.jar;Jar Description String". Example: - *

-     * libraries=com.example.foo;com.example.bar
-     * com.example.foo=foo.jar;Foo Library
-     * com.example.bar=bar.jar;Bar Library
-     * 
- * Not saved in source.properties. - */ - public static final String ADDON_LIBRARIES = "libraries"; //$NON-NLS-1$ - - /** - * An optional default skin string of the add-on.
- * Not saved in source.properties. - */ - public static final String ADDON_DEFAULT_SKIN = "skin"; //$NON-NLS-1$ - - /** - * An optional USB vendor string for the add-on.
- * Not saved in source.properties. - */ - public static final String ADDON_USB_VENDOR = "usb-vendor"; //$NON-NLS-1$ - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/FullRevision.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/FullRevision.java deleted file mode 100644 index e71499f8..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/FullRevision.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - -import com.android.annotations.NonNull; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Package multi-part revision number composed of a tuple - * (major.minor.micro) and an optional preview revision - * (the lack of a preview number indicates it's not a preview - * but a final package.) - * - * @see MajorRevision - */ -public class FullRevision implements Comparable { - - public static final int MISSING_MAJOR_REV = 0; - public static final int IMPLICIT_MINOR_REV = 0; - public static final int IMPLICIT_MICRO_REV = 0; - public static final int NOT_A_PREVIEW = 0; - - /** Only major revision specified: 1 term */ - protected static final int PRECISION_MAJOR = 1; - /** Only major and minor revisions specified: 2 terms (x.y) */ - protected static final int PRECISION_MINOR = 2; - /** Major, minor and micro revisions specified: 3 terms (x.y.z) */ - protected static final int PRECISION_MICRO = 3; - /** Major, minor, micro and preview revisions specified: 4 terms (x.y.z-rcN) */ - protected static final int PRECISION_PREVIEW = 4; - - public static final FullRevision NOT_SPECIFIED = new FullRevision(MISSING_MAJOR_REV); - - private static final Pattern FULL_REVISION_PATTERN = - // 1=major 2=minor 3=micro 4=separator 5=previewType 6=preview - Pattern.compile("\\s*([0-9]+)(?:\\.([0-9]+)(?:\\.([0-9]+))?)?([\\s-]*)?(?:(rc|alpha|beta)([0-9]+))?\\s*"); - - protected static final String DEFAULT_SEPARATOR = " "; - - private final int mMajor; - private final int mMinor; - private final int mMicro; - private final int mPreview; - private final String mPreviewSeparator; - private final PreviewType mPreviewType; - - public enum PreviewType { - ALPHA("alpha"), - BETA("beta"), - RC("rc") - ; - - final String name; - - PreviewType(String name) { - this.name = name; - } - } - - public FullRevision(int major) { - this(major, IMPLICIT_MINOR_REV, IMPLICIT_MICRO_REV); - } - - public FullRevision(int major, int minor, int micro) { - this(major, minor, micro, NOT_A_PREVIEW); - } - - public FullRevision(int major, int minor, int micro, int preview) { - this(major, minor, micro, PreviewType.RC, preview, DEFAULT_SEPARATOR); - } - - public FullRevision(int major, int minor, int micro, @NonNull PreviewType previewType, - int preview, @NonNull String previewSeparator) { - mMajor = major; - mMinor = minor; - mMicro = micro; - mPreview = preview; - mPreviewSeparator = previewSeparator; - mPreviewType = previewType; - } - - public int getMajor() { - return mMajor; - } - - public int getMinor() { - return mMinor; - } - - public int getMicro() { - return mMicro; - } - - @NonNull - protected String getSeparator() { - return mPreviewSeparator; - } - - public boolean isPreview() { - return mPreview > NOT_A_PREVIEW; - } - - public int getPreview() { - return mPreview; - } - - /** - * Parses a string of format "major.minor.micro rcPreview" and returns - * a new {@link FullRevision} for it. All the fields except major are - * optional. - *

- * The parsing is equivalent to the pseudo-BNF/regexp: - *

-     *   Major/Minor/Micro/Preview := [0-9]+
-     *   Revision := Major ('.' Minor ('.' Micro)? )? \s* ('rc'Preview)?
-     * 
- * - * @param revision A non-null revision to parse. - * @return A new non-null {@link FullRevision}. - * @throws NumberFormatException if the parsing failed. - */ - @NonNull - public static FullRevision parseRevision(@NonNull String revision) - throws NumberFormatException { - return parseRevisionImpl(revision, true /*supportMinorMicro*/, true /*supportPreview*/, - false /*keepPrevision*/); - } - - @NonNull - protected static FullRevision parseRevisionImpl(@NonNull String revision, - boolean supportMinorMicro, - boolean supportPreview, - boolean keepPrecision) - throws NumberFormatException { - if (revision == null) { - throw new NumberFormatException("revision is "); //$NON-NLS-1$ - } - - Throwable cause = null; - String error = null; - try { - Matcher m = FULL_REVISION_PATTERN.matcher(revision); - if (m != null && m.matches()) { - int major = Integer.parseInt(m.group(1)); - - int minor = IMPLICIT_MINOR_REV; - int micro = IMPLICIT_MICRO_REV; - int preview = NOT_A_PREVIEW; - int precision = PRECISION_MAJOR; - String previewSeparator = " "; - PreviewType previewType = PreviewType.RC; - - String s = m.group(2); - if (s != null) { - if (!supportMinorMicro) { - error = " -- Minor number not supported"; //$NON-NLS-1$ - } else { - minor = Integer.parseInt(s); - precision = PRECISION_MINOR; - } - } - - s = m.group(3); - if (s != null) { - if (!supportMinorMicro) { - error = " -- Micro number not supported"; //$NON-NLS-1$ - } else { - micro = Integer.parseInt(s); - precision = PRECISION_MICRO; - } - } - - s = m.group(6); - if (s != null) { - if (!supportPreview) { - error = " -- Preview number not supported"; //$NON-NLS-1$ - } else { - preview = Integer.parseInt(s); - previewSeparator = m.group(4); - precision = PRECISION_PREVIEW; - - String previewTypeName = m.group(5); - for (PreviewType pt : PreviewType.values()) { - if (pt.name.equals(previewTypeName)) { - previewType = pt; - break; - } - } - } - } - - if (error == null) { - if (keepPrecision) { - return new PreciseRevision(major, minor, micro, preview, precision, - previewSeparator); - } else { - return new FullRevision(major, minor, micro, previewType, preview, previewSeparator); - } - } - } - } catch (Throwable t) { - cause = t; - } - - NumberFormatException n = new NumberFormatException( - "Invalid revision: " //$NON-NLS-1$ - + revision - + (error == null ? "" : error)); - if (cause != null) { - n.initCause(cause); - } - throw n; - } - - /** - * Returns the version in a fixed format major.minor.micro - * with an optional "rc preview#". For example it would - * return "18.0.0", "18.1.0" or "18.1.2 rc5". - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(mMajor) - .append('.').append(mMinor) - .append('.').append(mMicro); - - if (mPreview != NOT_A_PREVIEW) { - sb.append(mPreviewSeparator).append(mPreviewType.name).append(mPreview); - } - - return sb.toString(); - } - - /** - * Returns the version in a dynamic format "major.minor.micro rc#". - * This is similar to {@link #toString()} except it omits minor, micro - * or preview versions when they are zero. - * For example it would return "18 rc1" instead of "18.0.0 rc1", - * or "18.1 rc2" instead of "18.1.0 rc2". - */ - public String toShortString() { - StringBuilder sb = new StringBuilder(); - sb.append(mMajor); - if (mMinor > 0 || mMicro > 0) { - sb.append('.').append(mMinor); - } - if (mMicro > 0) { - sb.append('.').append(mMicro); - } - if (mPreview != NOT_A_PREVIEW) { - sb.append(mPreviewSeparator).append(mPreviewType.name).append(mPreview); - } - - return sb.toString(); - } - - /** - * Returns the version number as an integer array, in the form - * [major, minor, micro] or [major, minor, micro, preview]. - * - * This is useful to initialize an instance of - * {@code org.apache.tools.ant.util.DeweyDecimal} using a - * {@link FullRevision}. - * - * @param includePreview If true the output will contain 4 fields - * to include the preview number (even if 0.) If false the output - * will contain only 3 fields (major, minor and micro.) - * @return A new int array, never null, with either 3 or 4 fields. - */ - public int[] toIntArray(boolean includePreview) { - int size = includePreview ? 4 : 3; - int[] result = new int[size]; - result[0] = mMajor; - result[1] = mMinor; - result[2] = mMicro; - if (result.length > 3) { - result[3] = mPreview; - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + mMajor; - result = prime * result + mMinor; - result = prime * result + mMicro; - result = prime * result + mPreview; - result = prime * result + mPreviewType.hashCode(); - return result; - } - - @Override - public boolean equals(Object rhs) { - if (this == rhs) { - return true; - } - if (rhs == null) { - return false; - } - if (!(rhs instanceof FullRevision)) { - return false; - } - FullRevision other = (FullRevision) rhs; - if (mMajor != other.mMajor) { - return false; - } - if (mMinor != other.mMinor) { - return false; - } - if (mMicro != other.mMicro) { - return false; - } - if (mPreview != other.mPreview) { - return false; - } - if (mPreviewType != other.mPreviewType) { - return false; - } - return true; - } - - /** - * Trivial comparison of a version, e.g 17.1.2 < 18.0.0. - * - * Note that preview/release candidate are released before their final version, - * so "18.0.0 rc1" comes below "18.0.0". The best way to think of it as if the - * lack of preview number was "+inf": - * "18.1.2 rc5" => "18.1.2.5" so its less than "18.1.2.+INF" but more than "18.1.1.0" - * and more than "18.1.2.4" - * - * @param rhs The right-hand side {@link FullRevision} to compare with. - * @return <0 if lhs < rhs; 0 if lhs==rhs; >0 if lhs > rhs. - */ - @Override - public int compareTo(FullRevision rhs) { - return compareTo(rhs, PreviewComparison.COMPARE_NUMBER); - } - - /** - * Trivial comparison of a version, e.g 17.1.2 < 18.0.0. - * - * Note that preview/release candidate are released before their final version, - * so "18.0.0 rc1" comes below "18.0.0". The best way to think of it as if the - * lack of preview number was "+inf": - * "18.1.2 rc5" => "18.1.2.5" so its less than "18.1.2.+INF" but more than "18.1.1.0" - * and more than "18.1.2.4" - * - * @param rhs The right-hand side {@link FullRevision} to compare with. - * @param comparePreview How to compare the preview value. - * @return <0 if lhs < rhs; 0 if lhs==rhs; >0 if lhs > rhs. - */ - public int compareTo(FullRevision rhs, PreviewComparison comparePreview) { - int delta = mMajor - rhs.mMajor; - if (delta != 0) { - return delta; - } - - delta = mMinor - rhs.mMinor; - if (delta != 0) { - return delta; - } - - delta = mMicro - rhs.mMicro; - if (delta != 0) { - return delta; - } - - int p1, p2; - switch (comparePreview) { - case IGNORE: - // Nothing to compare. - break; - - case COMPARE_NUMBER: - if (!mPreviewType.equals(rhs.mPreviewType)) { - return mPreviewType.compareTo(rhs.mPreviewType); - } - - p1 = mPreview == NOT_A_PREVIEW ? Integer.MAX_VALUE : mPreview; - p2 = rhs.mPreview == NOT_A_PREVIEW ? Integer.MAX_VALUE : rhs.mPreview; - delta = p1 - p2; - break; - - case COMPARE_TYPE: - p1 = mPreview == NOT_A_PREVIEW ? 1 : 0; - p2 = rhs.mPreview == NOT_A_PREVIEW ? 1 : 0; - delta = p1 - p2; - break; - } - return delta; - } - - /** Indicates how to compare the preview field in - * {@link FullRevision#compareTo(FullRevision, PreviewComparison)} */ - public enum PreviewComparison { - /** Both revisions must have exactly the same preview number. */ - COMPARE_NUMBER, - /** Both revisions must have the same preview type (both must be previews - * or both must not be previews, but the actual number is irrelevant.) - * This is the most typical choice used to find updates of the same type. */ - COMPARE_TYPE, - /** The preview field is ignored and not used in the comparison. */ - IGNORE - } - - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IDescription.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IDescription.java deleted file mode 100644 index 1e44964d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IDescription.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2009 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.repository; - -/** - * Interface for elements that can provide a description of themselves. - */ -public interface IDescription { - - /** - * Returns a description of the given element. Cannot be null. - *

- * A description is a multi-line of text, typically much more - * elaborate than what {@link Object#toString()} would provide. - */ - String getShortDescription(); - - /** - * Returns a description of the given element. Cannot be null. - *

- * A description is a multi-line of text, typically much more - * elaborate than what {@link Object#toString()} would provide. - */ - String getLongDescription(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IListDescription.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IListDescription.java deleted file mode 100644 index c3ae3653..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/IListDescription.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 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.repository; - -/** - * Interface for elements that can provide a description of themselves. - */ -public interface IListDescription { - - /** - * Returns a description of this package that is suitable for a list display. - * Should not be empty. Must never be null. - *

- * Note that this is the "base" name for the package - * with no specific revision nor API mentioned. - * In contrast, {@link IDescription#getShortDescription()} should be used if you - * want more details such as the package revision number or the API, if applicable. - */ - String getListDescription(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/License.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/License.java deleted file mode 100644 index 7040ec11..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/License.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2009 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.repository; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.SdkManager; -import com.android.utils.FileUtils; -import com.google.common.base.Charsets; -import com.google.common.hash.Hashing; -import com.google.common.io.Files; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -/** - * License text, with an optional license XML reference. - */ -public class License { - private final String mLicense; - private final String mLicenseRef; - private final String mLicenseHash; - - private static final String LICENSE_DIR = "licenses"; - - public License(@NonNull String license, @Nullable String licenseRef) { - mLicense = license; - mLicenseRef = licenseRef; - mLicenseHash = Hashing.sha1().hashBytes(mLicense.getBytes()).toString(); - } - - /** Returns the license text. Never null. */ - @NonNull - public String getLicense() { - return mLicense; - } - - /** Returns the hash of the license text. Never null. */ - @NonNull - public String getLicenseHash() { - return mLicenseHash; - } - - /** - * Returns the license XML reference. - * Could be null, e.g. in tests or synthetic packages - * recreated from local source.properties. - */ - @Nullable - public String getLicenseRef() { - return mLicenseRef; - } - - /** - * Returns a string representation of the license, useful for debugging. - * This is not designed to be shown to the user. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(""); - return sb.toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((mLicense == null) ? 0 : mLicense.hashCode()); - result = prime * result - + ((mLicenseRef == null) ? 0 : mLicenseRef.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof License)) { - return false; - } - License other = (License) obj; - if (mLicense == null) { - if (other.mLicense != null) { - return false; - } - } else if (!mLicense.equals(other.mLicense)) { - return false; - } - if (mLicenseRef == null) { - if (other.mLicenseRef != null) { - return false; - } - } else if (!mLicenseRef.equals(other.mLicenseRef)) { - return false; - } - return true; - } - - /** - * Checks whether this license has previously been accepted. - * @param sdkRoot The root directory of the Android SDK - * @return true if this license has already been accepted - */ - public boolean checkAccepted(@Nullable File sdkRoot) { - if (sdkRoot == null) { - return false; - } - File licenseDir = new File(sdkRoot, LICENSE_DIR); - File licenseFile = new File(licenseDir, mLicenseRef == null ? mLicenseHash : mLicenseRef); - if (!licenseFile.exists()) { - return false; - } - try { - String hash = Files.readFirstLine(licenseFile, Charsets.UTF_8); - return hash.equals(mLicenseHash); - } catch (IOException e) { - return false; - } - } - - /** - * Marks this license as accepted. - * - * @param sdkRoot The root directory of the Android SDK - * @return true if the acceptance was persisted successfully. - */ - public boolean setAccepted(@Nullable File sdkRoot) { - if (sdkRoot == null) { - return false; - } - if (checkAccepted(sdkRoot)) { - return true; - } - File licenseDir = new File(sdkRoot, LICENSE_DIR); - if (licenseDir.exists() && !licenseDir.isDirectory()) { - return false; - } - if (!licenseDir.exists()) { - licenseDir.mkdir(); - } - File licenseFile = new File(licenseDir, mLicenseRef == null ? mLicenseHash : mLicenseRef); - try { - Files.write(mLicenseHash, licenseFile, Charsets.UTF_8); - } - catch (IOException e) { - return false; - } - return true; - } -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/MajorRevision.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/MajorRevision.java deleted file mode 100644 index b6d25573..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/MajorRevision.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - -import com.android.annotations.NonNull; - - -/** - * Package revision number composed of a single major revision. - *

- * Contrary to a {@link FullRevision}, a {@link MajorRevision} does not - * provide minor, micro and preview revision numbers -- these are all - * set to zero. - */ -public class MajorRevision extends FullRevision { - - public MajorRevision(FullRevision fullRevision) { - super(fullRevision.getMajor(), IMPLICIT_MINOR_REV, IMPLICIT_MICRO_REV); - } - - public MajorRevision(int major) { - super(major, IMPLICIT_MINOR_REV, IMPLICIT_MICRO_REV); - } - - @Override - public String toString() { - return super.toShortString(); - } - - /** - * Parses a single-integer string and returns a new {@link MajorRevision} for it. - * - * @param revision A non-null revision to parse. - * @return A new non-null {@link MajorRevision}. - * @throws NumberFormatException if the parsing failed. - */ - @NonNull - public static MajorRevision parseRevision(@NonNull String revision) - throws NumberFormatException { - FullRevision r = parseRevisionImpl( - revision, false /*supportMinorMicro*/, false /*supportPreview*/, - false /*keepPrecision*/); - return new MajorRevision(r.getMajor()); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/NoPreviewRevision.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/NoPreviewRevision.java deleted file mode 100644 index 0280cb28..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/NoPreviewRevision.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 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.repository; - -import com.android.annotations.NonNull; - - -/** - * Package multi-part revision number composed of a tuple - * (major.minor.micro) but without support for any optional preview number. - * - * @see FullRevision - */ -public class NoPreviewRevision extends FullRevision { - - public NoPreviewRevision(int major) { - this(major, IMPLICIT_MINOR_REV, IMPLICIT_MICRO_REV); - } - - public NoPreviewRevision(int major, int minor, int micro) { - super(major, minor, micro, NOT_A_PREVIEW); - } - - /** - * Parses a string of format "major.minor.micro" and returns - * a new {@link NoPreviewRevision} for it. All the fields except major are - * optional. - *

- * The parsing is equivalent to the pseudo-BNF/regexp: - *

-     *   Major/Minor/Micro/Preview := [0-9]+
-     *   Revision := Major ('.' Minor ('.' Micro)? )? \s*
-     * 
- * - * @param revision A non-null revision to parse. - * @return A new non-null {@link NoPreviewRevision}. - * @throws NumberFormatException if the parsing failed. - */ - @NonNull - public static NoPreviewRevision parseRevision(@NonNull String revision) - throws NumberFormatException { - FullRevision r = parseRevisionImpl( - revision, true /*supportMinorMicro*/, false /*supportPreview*/, - false /*keepPrecision*/); - return new NoPreviewRevision(r.getMajor(), r.getMinor(), r.getMicro()); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PkgProps.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PkgProps.java deleted file mode 100644 index 3126984f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PkgProps.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2011 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.sdklib.repository; - - - -/** - * Public constants used by the repository when saving {@code source.properties} - * files in local packages. - *

- * These constants are public and part of the SDK Manager public API. - * Once published we can't change them arbitrarily since various parts - * of our build process depend on them. - */ -public class PkgProps { - - // Base Package - public static final String PKG_REVISION = "Pkg.Revision"; //$NON-NLS-1$ - public static final String PKG_LICENSE = "Pkg.License"; //$NON-NLS-1$ - public static final String PKG_LICENSE_REF = "Pkg.LicenseRef"; //$NON-NLS-1$ - public static final String PKG_DESC = "Pkg.Desc"; //$NON-NLS-1$ - public static final String PKG_DESC_URL = "Pkg.DescUrl"; //$NON-NLS-1$ - public static final String PKG_RELEASE_NOTE = "Pkg.RelNote"; //$NON-NLS-1$ - public static final String PKG_RELEASE_URL = "Pkg.RelNoteUrl"; //$NON-NLS-1$ - public static final String PKG_SOURCE_URL = "Pkg.SourceUrl"; //$NON-NLS-1$ - public static final String PKG_OBSOLETE = "Pkg.Obsolete"; //$NON-NLS-1$ - public static final String PKG_LIST_DISPLAY = "Pkg.ListDisplay"; //$NON-NLS-1$ - - // AndroidVersion - - public static final String VERSION_API_LEVEL = "AndroidVersion.ApiLevel";//$NON-NLS-1$ - /** Code name of the platform if the platform is not final */ - public static final String VERSION_CODENAME = "AndroidVersion.CodeName";//$NON-NLS-1$ - - - // AddonPackage - - public static final String ADDON_NAME = "Addon.Name"; //$NON-NLS-1$ - public static final String ADDON_NAME_ID = "Addon.NameId"; //$NON-NLS-1$ - public static final String ADDON_NAME_DISPLAY = "Addon.NameDisplay"; //$NON-NLS-1$ - - public static final String ADDON_VENDOR = "Addon.Vendor"; //$NON-NLS-1$ - public static final String ADDON_VENDOR_ID = "Addon.VendorId"; //$NON-NLS-1$ - public static final String ADDON_VENDOR_DISPLAY = "Addon.VendorDisplay"; //$NON-NLS-1$ - - // DocPackage - - // ExtraPackage - - public static final String EXTRA_PATH = "Extra.Path"; //$NON-NLS-1$ - public static final String EXTRA_OLD_PATHS = "Extra.OldPaths"; //$NON-NLS-1$ - public static final String EXTRA_MIN_API_LEVEL = "Extra.MinApiLevel"; //$NON-NLS-1$ - public static final String EXTRA_PROJECT_FILES = "Extra.ProjectFiles"; //$NON-NLS-1$ - public static final String EXTRA_VENDOR = "Extra.Vendor"; //$NON-NLS-1$ - public static final String EXTRA_VENDOR_ID = "Extra.VendorId"; //$NON-NLS-1$ - public static final String EXTRA_VENDOR_DISPLAY = "Extra.VendorDisplay"; //$NON-NLS-1$ - public static final String EXTRA_NAME_DISPLAY = "Extra.NameDisplay"; //$NON-NLS-1$ - - // ILayoutlibVersion - - public static final String LAYOUTLIB_API = "Layoutlib.Api"; //$NON-NLS-1$ - public static final String LAYOUTLIB_REV = "Layoutlib.Revision"; //$NON-NLS-1$ - - // MinToolsPackage - - public static final String MIN_TOOLS_REV = "Platform.MinToolsRev"; //$NON-NLS-1$ - - // PlatformPackage - - public static final String PLATFORM_VERSION = "Platform.Version"; //$NON-NLS-1$ - /** Code name of the platform. This has no bearing on the package being a preview or not. */ - public static final String PLATFORM_CODENAME = "Platform.CodeName"; //$NON-NLS-1$ - public static final String PLATFORM_INCLUDED_ABI = "Platform.Included.Abi"; //$NON-NLS-1$ - - // ToolPackage - - public static final String MIN_PLATFORM_TOOLS_REV = "Platform.MinPlatformToolsRev";//$NON-NLS-1$ - public static final String MIN_BUILD_TOOLS_REV = "Platform.MinBuildToolsRev"; //$NON-NLS-1$ - - - // SamplePackage - - public static final String SAMPLE_MIN_API_LEVEL = "Sample.MinApiLevel"; //$NON-NLS-1$ - - // SystemImagePackage - - public static final String SYS_IMG_ABI = "SystemImage.Abi"; //$NON-NLS-1$ - public static final String SYS_IMG_TAG_ID = "SystemImage.TagId"; //$NON-NLS-1$ - public static final String SYS_IMG_TAG_DISPLAY = "SystemImage.TagDisplay"; //$NON-NLS-1$ -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PreciseRevision.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PreciseRevision.java deleted file mode 100644 index 81e97443..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/PreciseRevision.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2014 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.repository; - -import com.android.annotations.NonNull; - -/** - * A {@link FullRevision} which distinguishes between x and x.0, x.0.0, x.y.0, etc; it basically - * keeps track of the precision of the revision string. - *

- * This is vital when referencing Gradle artifact numbers, - * since versions x.y.0 and version x.y are not the same. - */ -public class PreciseRevision extends FullRevision { - private final int mPrecision; - - /** - * Parses a string of format "major.minor.micro rcPreview" and returns - * a new {@link com.android.sdklib.repository.PreciseRevision} for it. - * - * All the fields except major are optional. - *

- * @param revision A non-null revision to parse. - * @return A new non-null {@link com.android.sdklib.repository.PreciseRevision}. - * @throws NumberFormatException if the parsing failed. - */ - @NonNull - public static PreciseRevision parseRevision(@NonNull String revision) - throws NumberFormatException { - return (PreciseRevision) parseRevisionImpl(revision, true /*supportMinorMicro*/, - true /*supportPreview*/, true /*keepPrevision*/); - } - - public PreciseRevision(int major) { - this(major, IMPLICIT_MINOR_REV, IMPLICIT_MICRO_REV, NOT_A_PREVIEW, PRECISION_MAJOR, - DEFAULT_SEPARATOR); - } - - public PreciseRevision(int major, int minor) { - this(major, minor, IMPLICIT_MICRO_REV, NOT_A_PREVIEW, PRECISION_MINOR, DEFAULT_SEPARATOR); - } - - public PreciseRevision(int major, int minor, int micro) { - this(major, minor, micro, NOT_A_PREVIEW, PRECISION_MICRO, DEFAULT_SEPARATOR); - } - - public PreciseRevision(int major, int minor, int micro, int preview) { - this(major, minor, micro, preview, PRECISION_PREVIEW, DEFAULT_SEPARATOR); - } - - PreciseRevision(int major, int minor, int micro, int preview, int precision, - String separator) { - this(major, minor, micro, preview, precision, separator, PreviewType.RC); - } - - PreciseRevision(int major, int minor, int micro, int preview, int precision, - String separator, FullRevision.PreviewType previewType) { - super(major, minor, micro, previewType, preview, separator); - mPrecision = precision; - } - - /** - * Returns the version in a fixed format major.minor.micro - * with an optional "rc preview#". For example it would - * return "18.0.0", "18.1.0" or "18.1.2 rc5". - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(getMajor()); - - if (mPrecision >= PRECISION_MINOR) { - sb.append('.').append(getMinor()); - if (mPrecision >= PRECISION_MICRO) { - sb.append('.').append(getMicro()); - if (mPrecision >= PRECISION_PREVIEW && isPreview()) { - sb.append(getSeparator()).append("rc").append(getPreview()); - } - } - } - - return sb.toString(); - } - - @Override - public String toShortString() { - return toString(); - } - - @Override - public int[] toIntArray(boolean includePreview) { - int[] result; - if (mPrecision >= PRECISION_PREVIEW) { - if (includePreview) { - result = new int[mPrecision]; - result[3] = getPreview(); - } else { - result = new int[mPrecision - 1]; - } - } else { - result = new int[mPrecision]; - } - result[0] = getMajor(); - if (mPrecision >= PRECISION_MINOR) { - result[1] = getMinor(); - if (mPrecision >= PRECISION_MICRO) { - result[2] = getMicro(); - } - } - - return result; - } - - @Override - public int hashCode() { - return 31 * super.hashCode() + mPrecision; - } - - @Override - public boolean equals(Object rhs) { - boolean equals = super.equals(rhs); - if (equals) { - if (!(rhs instanceof PreciseRevision)) { - return false; - } - PreciseRevision other = (PreciseRevision) rhs; - return mPrecision == other.mPrecision; - } - return false; - } - - public int compareTo(PreciseRevision rhs, PreviewComparison comparePreview) { - int delta = super.compareTo(rhs, comparePreview); - if (delta == 0) { - return mPrecision - rhs.mPrecision; - } - return delta; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/README.txt b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/README.txt deleted file mode 100644 index e6e0f633..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/README.txt +++ /dev/null @@ -1,25 +0,0 @@ -This directory contains the XML Schemas (XSD) used by the Android SDK Repository. - -The repository exports all the packages that compose the SDK as well as -various manifest that define what is available in the repository. -The XML schemas available here allows clients to validate the manifests. - -TODO: -- overview of schemas -- principles of design -- principles of evolution vs revision numbers -- naming convention -- using by "make sdk_repo" - - -Naming Convention ------------------ - -Repository schemas are named sdk-type-N.xsd where -- type is either addon, addons-list or repository. -- N is the schema revision number, starting at 1 and increment with each revision. - -Schemas can also be named -sdk-type-N.xsd. -The dash prefix means this schema is a *future* schema that is not yet -used in production. This allows the repository to test future schemas -before they are deployed. diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoConstants.java deleted file mode 100644 index 44f6f15c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoConstants.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2010 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.sdklib.repository; - -import java.io.InputStream; - - - -/** - * Public constants common to the sdk-repository and sdk-addon XML Schemas. - * @deprecated moved to studio - */ -public class RepoConstants { - - /** The license definition. */ - public static final String NODE_LICENSE = "license"; //$NON-NLS-1$ - /** The optional uses-license for all packages or for a lib. */ - public static final String NODE_USES_LICENSE = "uses-license"; //$NON-NLS-1$ - /** The revision, an int > 0, for all packages. */ - public static final String NODE_REVISION = "revision"; //$NON-NLS-1$ - /** The optional description for all packages or for a lib. */ - public static final String NODE_DESCRIPTION = "description"; //$NON-NLS-1$ - /** The optional description URL for all packages. */ - public static final String NODE_DESC_URL = "desc-url"; //$NON-NLS-1$ - /** The optional release note for all packages. */ - public static final String NODE_RELEASE_NOTE = "release-note"; //$NON-NLS-1$ - /** The optional release note URL for all packages. */ - public static final String NODE_RELEASE_URL = "release-url"; //$NON-NLS-1$ - /** The optional obsolete qualifier for all packages. */ - public static final String NODE_OBSOLETE = "obsolete"; //$NON-NLS-1$ - /** The optional project-files provided by extra packages. */ - public static final String NODE_PROJECT_FILES = "project-files"; //$NON-NLS-1$ - - /** A system-image package. */ - public static final String NODE_SYSTEM_IMAGE = "system-image"; //$NON-NLS-1$ - - /* An included-ABI element for a system-image package. */ - public static final String NODE_ABI_INCLUDED = "included-abi"; //$NON-NLS-1$ - /* An ABI element for a system-image package. */ - public static final String NODE_ABI = "abi"; //$NON-NLS-1$ - - /** The optional minimal tools revision required by platform & extra packages. */ - public static final String NODE_MIN_TOOLS_REV = "min-tools-rev"; //$NON-NLS-1$ - /** The optional minimal platform-tools revision required by tool packages. */ - public static final String NODE_MIN_PLATFORM_TOOLS_REV = "min-platform-tools-rev"; //$NON-NLS-1$ - /** The optional minimal API level required by extra packages. */ - public static final String NODE_MIN_API_LEVEL = "min-api-level"; //$NON-NLS-1$ - - /** The version, a string, for platform packages. */ - public static final String NODE_VERSION = "version"; //$NON-NLS-1$ - /** The api-level, an int > 0, for platform, add-on and doc packages. */ - public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$ - /** The codename, a string, for platform packages. */ - public static final String NODE_CODENAME = "codename"; //$NON-NLS-1$ - /** The *old* vendor, a string, for add-on and extra packages. - * Replaced by {@link #NODE_VENDOR_DISPLAY} and {@link #NODE_VENDOR_ID} in addon-v4.xsd. */ - public static final String NODE_VENDOR = "vendor"; //$NON-NLS-1$ - /** The vendor display string, for add-on and extra packages. */ - public static final String NODE_VENDOR_DISPLAY = "vendor-display"; //$NON-NLS-1$ - /** The unique vendor id string, for add-on and extra packages. */ - public static final String NODE_VENDOR_ID = "vendor-id"; //$NON-NLS-1$ - /** The name, a string, for add-on packages or for libraries. - * Replaced by {@link #NODE_NAME_DISPLAY} and {@link #NODE_NAME_ID} in addon-v4.xsd. */ - public static final String NODE_NAME = "name"; //$NON-NLS-1$ - /** The name display string, for add-on packages or for libraries. */ - public static final String NODE_NAME_DISPLAY = "name-display"; //$NON-NLS-1$ - /** The unique name id string, for add-on packages or for libraries. */ - public static final String NODE_NAME_ID = "name-id"; //$NON-NLS-1$ - /** The optional string used to display a package in a list view. */ - public static final String NODE_LIST_DISPLAY = "list-display"; //$NON-NLS-1$ - - /** A layoutlib package. */ - public static final String NODE_LAYOUT_LIB = "layoutlib"; //$NON-NLS-1$ - /** The API integer for a layoutlib element. */ - public static final String NODE_API = "api"; //$NON-NLS-1$ - - /** The libs container, optional for an add-on. */ - public static final String NODE_LIBS = "libs"; //$NON-NLS-1$ - /** A lib element in a libs container. */ - public static final String NODE_LIB = "lib"; //$NON-NLS-1$ - - /** The path segment, a string, for extra packages. */ - public static final String NODE_PATH = "path"; //$NON-NLS-1$ - - /** The old_path segments, a string, for extra packages. */ - public static final String NODE_OLD_PATHS = "old-paths"; //$NON-NLS-1$ - - /** The archives container, for all packages. */ - public static final String NODE_ARCHIVES = "archives"; //$NON-NLS-1$ - /** An archive element, for the archives container. */ - public static final String NODE_ARCHIVE = "archive"; //$NON-NLS-1$ - - /** An archive size, an int > 0. */ - public static final String NODE_SIZE = "size"; //$NON-NLS-1$ - /** A sha1 archive checksum, as a 40-char hex. */ - public static final String NODE_CHECKSUM = "checksum"; //$NON-NLS-1$ - /** A download archive URL, either absolute or relative to the repository xml. */ - public static final String NODE_URL = "url"; //$NON-NLS-1$ - - /** - * Optional element to indicate an archive is only suitable for the specified OS.
- * Values: windows | macosx | linux. - * @since repo-10, addon-7 and sys-img-3. - * @replaces {@link #LEGACY_ATTR_OS} - */ - public static final String NODE_HOST_OS = "host-os"; //$NON-NLS-1$ - /** - * Optional element to indicate an archive is only suitable for the specified host bit size.
- * Values: 32 | 64. - * @since repo-10, addon-7 and sys-img-3. - */ - public static final String NODE_HOST_BITS = "host-bits"; //$NON-NLS-1$ - /** - * Optional element to indicate an archive is only suitable for the specified JVM bit size.
- * Values: 32 | 64. - * @since repo-10, addon-7 and sys-img-3. - * @replaces {@link #LEGACY_ATTR_ARCH} - */ - public static final String NODE_JVM_BITS = "jvm-bits"; //$NON-NLS-1$ - /** - * Optional element to indicate an archive is only suitable for a JVM equal or greater than - * the specified value.
- * Value format: [1-9](\.[0-9]{1,2}){0,2}, e.g. "1.6", "1.7.0", "1.10" or "2" - * @since repo-10, addon-7 and sys-img-3. - */ - public static final String NODE_MIN_JVM_VERSION = "min-jvm-version"; //$NON-NLS-1$ - - - /** An archive checksum type, mandatory. */ - public static final String ATTR_TYPE = "type"; //$NON-NLS-1$ - /** - * An archive OS attribute, mandatory.
- * Use {@link #NODE_HOST_OS} instead in repo-10, addon-7 and sys-img-3. - */ - public static final String LEGACY_ATTR_OS = "os"; //$NON-NLS-1$ - /** - * An optional archive Architecture attribute.
- * Use {@link #NODE_JVM_BITS} instead in repo-10, addon-7 and sys-img-3. - */ - public static final String LEGACY_ATTR_ARCH = "arch"; //$NON-NLS-1$ - - /** A license definition ID. */ - public static final String ATTR_ID = "id"; //$NON-NLS-1$ - /** A license reference. */ - public static final String ATTR_REF = "ref"; //$NON-NLS-1$ - - - /** Type of a sha1 checksum. */ - public static final String SHA1_TYPE = "sha1"; //$NON-NLS-1$ - - /** Length of a string representing a SHA1 checksum; always 40 characters long. */ - public static final int SHA1_CHECKSUM_LEN = 40; - - /** - * Temporary folder used to hold downloads and extract archives during installation. - * This folder will be located in the SDK. - */ - public static final String FD_TEMP = "temp"; //$NON-NLS-1$ - - /** - * Returns a stream to the requested XML Schema. - * This is an internal helper. Users of the library should call - * {@link SdkRepoConstants#getXsdStream(String, int)} or - * {@link SdkAddonConstants#getXsdStream(String, int)}. - * - * @param rootElement The root of the filename of the XML schema. - * This is by convention the same as the root element declared by the schema. - * @param version The XML schema revision number, an integer >= 1. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - * @see SdkRepoConstants#getXsdStream(int) - * @see SdkAddonConstants#getXsdStream(int) - */ - protected static InputStream getXsdStream(String rootElement, int version) { - String filename = String.format("%1$s-%2$02d.xsd", rootElement, version); //$NON-NLS-1$ - - InputStream stream = null; - try { - stream = RepoConstants.class.getResourceAsStream(filename); - } catch (Exception e) { - // Some implementations seem to return null on failure, - // others throw an exception. We want to return null. - } - if (stream == null) { - // Try the alternate schemas that are not published yet. - // This allows us to internally test with new schemas before the - // public repository uses it. - filename = String.format("-%1$s-%2$02d.xsd", rootElement, version); //$NON-NLS-1$ - try { - stream = RepoConstants.class.getResourceAsStream(filename); - } catch (Exception e) { - // Some implementations seem to return null on failure, - // others throw an exception. We want to return null. - } - } - - return stream; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoXsdUtil.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoXsdUtil.java deleted file mode 100644 index 805fa8a9..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/RepoXsdUtil.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2015 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.repository; - -import com.google.common.collect.Lists; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.List; -import java.util.logging.Logger; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.stream.StreamSource; - -/** - * Utilities related to the respository XSDs. - */ -public class RepoXsdUtil { - - public static final String NODE_IMPORT = "import"; - public static final String NODE_INCLUDE = "include"; - - public static final String ATTR_SCHEMA_LOCATION = "schemaLocation"; - - - /** - * Gets StreamSources for the given xsd (implied by the name and version), as well as any xsds imported or included by the main one. - * - * @param rootElement The root of the filename of the XML schema. This is by convention the same - * as the root element declared by the schema. - * @param version The XML schema revision number, an integer >= 1. - */ - public static StreamSource[] getXsdStream(final String rootElement, int version) { - String filename = String.format("%1$s-%2$02d.xsd", rootElement, version); //$NON-NLS-1$ - final List streams = Lists.newArrayList(); - InputStream stream = null; - try { - stream = RepoXsdUtil.class.getResourceAsStream(filename); - if (stream == null) { - filename = String.format("%1$s-%2$d.xsd", rootElement, version); //$NON-NLS-1$ - stream = RepoXsdUtil.class.getResourceAsStream(filename); - } - if (stream == null) { - // Try the alternate schemas that are not published yet. - // This allows us to internally test with new schemas before the - // public repository uses it. - filename = String.format("-%1$s-%2$02d.xsd", rootElement, version); //$NON-NLS-1$ - stream = RepoXsdUtil.class.getResourceAsStream(filename); - } - - // Parse the schema and find any imports or includes so we can return them as well. - // Currently transitive includes are not supported. - SAXParserFactory.newInstance().newSAXParser().parse(stream, new DefaultHandler() { - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { - name = name.substring(name.indexOf(':') + 1); - if (name.equals(NODE_IMPORT) || name.equals(NODE_INCLUDE)) { - String importFile = attributes.getValue(ATTR_SCHEMA_LOCATION); - streams.add(new StreamSource(RepoXsdUtil.class.getResourceAsStream(importFile))); - } - } - }); - // create and add the first stream again, since SaxParser closes the original one - streams.add(new StreamSource(RepoXsdUtil.class.getResourceAsStream(filename))); - } catch (Exception e) { - // Some implementations seem to return null on failure, - // others throw an exception. We want to return null. - return null; - } - return streams.toArray(new StreamSource[streams.size()]); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonConstants.java deleted file mode 100644 index 805f85b2..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonConstants.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2010 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.sdklib.repository; - - -import java.io.InputStream; - -/** - * Public constants for the sdk-addon XML Schema. - * @deprecated moved to studio - */ -public class SdkAddonConstants extends RepoConstants { - - /** - * The latest version of the sdk-addon XML Schema. - * Valid version numbers are between 1 and this number, included. - */ - public static final int NS_LATEST_VERSION = 7; - - /** - * The default name looked for by SdkSource when trying to load an - * sdk-addon XML if the URL doesn't match an existing resource. - */ - public static final String URL_DEFAULT_FILENAME = "addon.xml"; //$NON-NLS-1$ - - /** The base of our sdk-addon XML namespace. */ - private static final String NS_BASE = - "http://schemas.android.com/sdk/android/addon/"; //$NON-NLS-1$ - - /** - * The pattern of our sdk-addon XML namespace. - * Matcher's group(1) is the schema version (integer). - */ - public static final String NS_PATTERN = NS_BASE + "([0-9]+)"; //$NON-NLS-1$ - - /** The XML namespace of the latest sdk-addon XML. */ - public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION); - - /** The root sdk-addon element */ - public static final String NODE_SDK_ADDON = "sdk-addon"; //$NON-NLS-1$ - - /** An add-on package. */ - public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$ - - /** An extra package. */ - public static final String NODE_EXTRA = "extra"; //$NON-NLS-1$ - - /** - * List of possible nodes in a repository XML. Used to populate options automatically - * in the no-GUI mode. - */ - public static final String[] NODES = { - NODE_ADD_ON, - NODE_EXTRA - }; - - /** - * Returns a stream to the requested {@code sdk-addon} XML Schema. - * - * @param version Between 1 and {@link #NS_LATEST_VERSION}, included. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - */ - public static InputStream getXsdStream(int version) { - return getXsdStream(NODE_SDK_ADDON, version); - } - - /** - * Returns the URI of the sdk-addon schema for the given version number. - * @param version Between 1 and {@link #NS_LATEST_VERSION} included. - */ - public static String getSchemaUri(int version) { - return String.format(NS_BASE + "%d", version); //$NON-NLS-1$ - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonsListConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonsListConstants.java deleted file mode 100644 index 3468b778..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkAddonsListConstants.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2010 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.sdklib.repository; - - -import java.io.InputStream; - -/** - * Public constants for the sdk-addons-list XML Schema. - * @deprecated moved to studio - */ -public class SdkAddonsListConstants { - - /** The base of our sdk-addons-list XML namespace. */ - private static final String NS_BASE = - "http://schemas.android.com/sdk/android/addons-list/"; //$NON-NLS-1$ - - /** - * The pattern of our sdk-addons-list XML namespace. - * Matcher's group(1) is the schema version (integer). - */ - public static final String NS_PATTERN = NS_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$ - - /** The latest version of the sdk-addons-list XML Schema. - * Valid version numbers are between 1 and this number, included. */ - public static final int NS_LATEST_VERSION = 2; - - /** The XML namespace of the latest sdk-addons-list XML. */ - public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION); - - - /** The canonical URL filename for addons-list XML files. */ - public static final String URL_DEFAULT_FILENAME = getDefaultName(NS_LATEST_VERSION); - - /** The URL where to find the official addons list fle. */ - public static final String URL_ADDON_LIST = - SdkRepoConstants.URL_GOOGLE_SDK_SITE + URL_DEFAULT_FILENAME; - - - - /** The root sdk-addons-list element */ - public static final String NODE_SDK_ADDONS_LIST = "sdk-addons-list"; //$NON-NLS-1$ - - /** An add-on site. */ - public static final String NODE_ADDON_SITE = "addon-site"; //$NON-NLS-1$ - - /** A system image site. */ - public static final String NODE_SYS_IMG_SITE = "sys-img-site"; //$NON-NLS-1$ - - /** The UI-visible name of the add-on site. */ - public static final String NODE_NAME = "name"; //$NON-NLS-1$ - - /** - * The URL of the site. - *

- * This can be either the exact URL of the an XML resource conforming - * to the latest sdk-addon-N.xsd schema, or it can be the URL of a - * 'directory', in which case the manager will look for a resource - * named 'addon.xml' at this location. - *

- * Examples: - *

-     *    http://www.example.com/android/my_addons.xml
-     *  or
-     *    http://www.example.com/android/
-     * 
- * In the second example, the manager will actually look for - * http://www.example.com/android/addon.xml - */ - public static final String NODE_URL = "url"; //$NON-NLS-1$ - - /** - * Returns a stream to the requested sdk-addon XML Schema. - * - * @param version Between 1 and {@link #NS_LATEST_VERSION}, included. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - */ - public static InputStream getXsdStream(int version) { - String filename = String.format("sdk-addons-list-%d.xsd", version); //$NON-NLS-1$ - return SdkAddonsListConstants.class.getResourceAsStream(filename); - } - - /** - * Returns the URI of the sdk-addon schema for the given version number. - * @param version Between 1 and {@link #NS_LATEST_VERSION} included. - */ - public static String getSchemaUri(int version) { - return String.format(NS_BASE + "%d", version); //$NON-NLS-1$ - } - - public static String getDefaultName(int version) { - return String.format("addons_list-%1$d.xml", version); //$NON-NLS-1$ - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkRepoConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkRepoConstants.java deleted file mode 100644 index 7b325432..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkRepoConstants.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2009 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.sdklib.repository; - - -import com.android.annotations.NonNull; - -import java.io.InputStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Public constants for the sdk-repository XML Schema. - * @deprecated moved to studio - */ -public class SdkRepoConstants extends RepoConstants { - - /** - * The latest version of the sdk-repository XML Schema. - * Valid version numbers are between 1 and this number, included. - */ - public static final int NS_LATEST_VERSION = 11; - - /** - * The min version of the sdk-repository XML Schema we'll try to load. - * When looking for a repository-N.xml on the server, we'll check from - * {@link #NS_LATEST_VERSION} down to this revision. - * We only introduced the "repository-N.xml" pattern start with revision - * 5, so we know that our server will never contain a repository - * XML with a schema version lower than this one. - */ - public static final int NS_SERVER_MIN_VERSION = 5; - - /** - * The URL of the official Google sdk-repository site. - * The URL ends with a /, allowing easy concatenation. - * */ - public static final String URL_GOOGLE_SDK_SITE = - "https://dl.google.com/android/repository/"; //$NON-NLS-1$ - - /** - * The default name looked for by SdkSource when trying to load an - * sdk-repository XML if the URL doesn't match an existing resource. - */ - public static final String URL_DEFAULT_FILENAME = "repository.xml"; //$NON-NLS-1$ - - /** - * The pattern name looked by {@link SdkSource} when trying to load - * an sdk-repository XML that is specific to a given XSD revision. - *

- * This must be used with {@link String#format(String, Object...)} with - * one integer parameter between 1 and {@link #NS_LATEST_VERSION}. - */ - public static final String URL_FILENAME_PATTERN = "repository-%1$d.xml"; //$NON-NLS-1$ - - /** The base of our sdk-repository XML namespace. */ - private static final String NS_BASE = - "http://schemas.android.com/sdk/android/repository/"; //$NON-NLS-1$ - - /** - * The pattern of our sdk-repository XML namespace. - * Matcher's group(1) is the schema version (integer). - */ - public static final String NS_PATTERN = NS_BASE + "([0-9]+)"; //$NON-NLS-1$ - - /** The XML namespace of the latest sdk-repository XML. */ - public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION); - - /** The root sdk-repository element */ - public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$ - - /* The major revision for tool and platform-tool package - * (the full revision number is revision.minor.micro + preview#.) - * Mandatory int > 0. 0 when missing, which should not happen in - * a valid document. */ - public static final String NODE_MAJOR_REV = "major"; //$NON-NLS-1$ - /* The minor revision for tool and platform-tool package - * (the full revision number is revision.minor.micro + preview#.) - * Optional int >= 0. Implied to be 0 when missing. */ - public static final String NODE_MINOR_REV = "minor"; //$NON-NLS-1$ - /* The micro revision for tool and platform-tool package - * (the full revision number is revision.minor.micro + preview#.) - * Optional int >= 0. Implied to be 0 when missing. */ - public static final String NODE_MICRO_REV = "micro"; //$NON-NLS-1$ - /* The preview revision for tool and platform-tool package. - * Int > 0, only present for "preview / release candidate" packages. */ - public static final String NODE_PREVIEW = "preview"; //$NON-NLS-1$ - - /** A platform package. */ - public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$ - /** A tool package. */ - public static final String NODE_TOOL = "tool"; //$NON-NLS-1$ - /** A platform-tool package. */ - public static final String NODE_PLATFORM_TOOL = "platform-tool"; //$NON-NLS-1$ - /** A build-tool package. */ - public static final String NODE_BUILD_TOOL = "build-tool"; //$NON-NLS-1$ - /** A doc package. */ - public static final String NODE_DOC = "doc"; //$NON-NLS-1$ - /** A sample package. */ - public static final String NODE_SAMPLE = "sample"; //$NON-NLS-1$ - /** A source package. */ - public static final String NODE_SOURCE = "source"; //$NON-NLS-1$ - - /** - * List of possible nodes in a repository XML. Used to populate options automatically - * in the no-GUI mode. - */ - public static final String[] NODES = { - NODE_PLATFORM, - NODE_SYSTEM_IMAGE, - NODE_TOOL, - NODE_PLATFORM_TOOL, - NODE_DOC, - NODE_SAMPLE, - NODE_SOURCE, - }; - - /** - * Returns a stream to the requested {@code sdk-repository} XML Schema. - * - * @param version Between 1 and {@link #NS_LATEST_VERSION}, included. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - */ - public static InputStream getXsdStream(int version) { - return getXsdStream(NODE_SDK_REPOSITORY, version); - } - - /** - * Returns the URI of the SDK Repository schema for the given version number. - * @param version Between 1 and {@link #NS_LATEST_VERSION} included. - */ - public static String getSchemaUri(int version) { - return String.format(NS_BASE + "%d", version); //$NON-NLS-1$ - } - - /** - * Checks whether the schema version is greater or equal to the specified one. - * - * @param nsUri A non-null sdk-repository schema URI. - * @param minVersion The minimum version accepted. - * @return True if the URI is valid and has at least the required version. False otherwise. - */ - public static boolean versionGreaterOrEqualThan(@NonNull String nsUri, int minVersion) { - Pattern nsPattern = Pattern.compile(SdkRepoConstants.NS_PATTERN); - Matcher m = nsPattern.matcher(nsUri); - if (m.matches()) { - String version = m.group(1); - try { - return Integer.parseInt(version) >= minVersion; - } catch (NumberFormatException e) { - } - } - return false; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkStatsConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkStatsConstants.java deleted file mode 100644 index df3e5d6d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkStatsConstants.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2012 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.sdklib.repository; - - -import java.io.InputStream; - -/** - * Public constants for the sdk-stats XML Schema. - * @deprecated moved to studio - */ -public class SdkStatsConstants { - - /** The canonical URL filename for addons-list XML files. */ - public static final String URL_DEFAULT_FILENAME = "stats-1.xml"; //$NON-NLS-1$ - - /** The URL where to find the official addons list fle. */ - public static final String URL_STATS = - SdkRepoConstants.URL_GOOGLE_SDK_SITE + URL_DEFAULT_FILENAME; - - /** The base of our sdk-addons-list XML namespace. */ - private static final String NS_BASE = - "http://schemas.android.com/sdk/android/stats/"; //$NON-NLS-1$ - - /** - * The pattern of our sdk-stats XML namespace. - * Matcher's group(1) is the schema version (integer). - */ - public static final String NS_PATTERN = NS_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$ - - /** The latest version of the sdk-stats XML Schema. - * Valid version numbers are between 1 and this number, included. */ - public static final int NS_LATEST_VERSION = 1; - - /** The XML namespace of the latest sdk-stats XML. */ - public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION); - - /** The root sdk-stats element */ - public static final String NODE_SDK_STATS = "sdk-stats"; //$NON-NLS-1$ - - /** A platform stat. */ - public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$ - - /** The Android API Level for the platform. An int > 0. */ - public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$ - - /** The official codename for this platform, for example "Cupcake". */ - public static final String NODE_CODENAME = "codename"; //$NON-NLS-1$ - - /** The official version name of this platform, for example "Android 1.5". */ - public static final String NODE_VERSION = "version"; //$NON-NLS-1$ - - /** - * The approximate share percentage of that platform. - * See the caveat in sdk-stats-1.xsd about value freshness and accuracy. - */ - public static final String NODE_SHARE = "share"; //$NON-NLS-1$ - - /** - * Returns a stream to the requested sdk-stats XML Schema. - * - * @param version Between 1 and {@link #NS_LATEST_VERSION}, included. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - */ - public static InputStream getXsdStream(int version) { - String filename = String.format("sdk-stats-%d.xsd", version); //$NON-NLS-1$ - return SdkStatsConstants.class.getResourceAsStream(filename); - } - - /** - * Returns the URI of the sdk-stats schema for the given version number. - * @param version Between 1 and {@link #NS_LATEST_VERSION} included. - */ - public static String getSchemaUri(int version) { - return String.format(NS_BASE + "%d", version); //$NON-NLS-1$ - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkSysImgConstants.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkSysImgConstants.java deleted file mode 100644 index d3e5752e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/SdkSysImgConstants.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2012 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.sdklib.repository; - - -import java.io.InputStream; - -/** - * Public constants for the sdk-sys-img XML Schema. - * @deprecated moved to studio - */ -public class SdkSysImgConstants extends RepoConstants { - - /** - * The default name looked for by SdkSource when trying to load an - * sdk-sys-img XML if the URL doesn't match an existing resource. - */ - public static final String URL_DEFAULT_FILENAME = "sys-img.xml"; //$NON-NLS-1$ - - /** The base of our sdk-sys-img XML namespace. */ - private static final String NS_BASE = - "http://schemas.android.com/sdk/android/sys-img/"; //$NON-NLS-1$ - - /** - * The pattern of our sdk-sys-img XML namespace. - * Matcher's group(1) is the schema version (integer). - */ - public static final String NS_PATTERN = NS_BASE + "([0-9]+)"; //$NON-NLS-1$ - - /** - * The latest version of the sdk-sys-img XML Schema. - * Valid version numbers are between 1 and this number, included. - */ - public static final int NS_LATEST_VERSION = 3; - - /** The XML namespace of the latest sdk-sys-img XML. */ - public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION); - - /** The root sdk-sys-img element */ - public static final String NODE_SDK_SYS_IMG = "sdk-sys-img"; //$NON-NLS-1$ - - /** A system-image tag id. */ - public static final String ATTR_TAG_ID = "tag-id"; //$NON-NLS-1$ - /** The user-visible display part of a system-image tag id. Optional. */ - public static final String ATTR_TAG_DISPLAY = "tag-display"; //$NON-NLS-1$ - - /** An add-on sub-element, indicating this is an add-on system image. */ - public static final String NODE_ADD_ON = SdkAddonConstants.NODE_ADD_ON; - - /** - * List of possible nodes in a repository XML. Used to populate options automatically - * in the no-GUI mode. - */ - public static final String[] NODES = { - NODE_SYSTEM_IMAGE, - }; - - /** - * Returns a stream to the requested {@code sdk-sys-img} XML Schema. - * - * @param version Between 1 and {@link #NS_LATEST_VERSION}, included. - * @return An {@link InputStream} object for the local XSD file or - * null if there is no schema for the requested version. - */ - public static InputStream getXsdStream(int version) { - return getXsdStream(NODE_SDK_SYS_IMG, version); - } - - /** - * Returns the URI of the sdk-sys-img schema for the given version number. - * @param version Between 1 and {@link #NS_LATEST_VERSION} included. - */ - public static String getSchemaUri(int version) { - return String.format(NS_BASE + "%d", version); //$NON-NLS-1$ - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgCapabilities.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgCapabilities.java deleted file mode 100644 index b481e6a6..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgCapabilities.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; - -/** - * {@link IPkgCapabilities} describe which attributes are available for each kind of - * SDK Manager package type. - *

- * To query packages capabilities, rely on {@code PkgType.hasXxx()} or {@code PkgDesc.hasXxx()}. - * - * @see PkgType - * @see PkgDesc - */ -public interface IPkgCapabilities { - - /** - * Indicates whether this package type has a {@link FullRevision}. - * @return True if this package type has a {@link FullRevision}. - */ - boolean hasFullRevision(); - - /** - * Indicates whether this package type has a {@link MajorRevision}. - * @return True if this package type has a {@link MajorRevision}. - */ - boolean hasMajorRevision(); - - /** - * Indicates whether this package type has a {@link AndroidVersion}. - * @return True if this package type has a {@link AndroidVersion}. - */ - boolean hasAndroidVersion(); - - /** - * Indicates whether this package type has a path. - * @return True if this package type has a path. - */ - boolean hasPath(); - - /** - * Indicates whether this package type has a tag. - * @return True if this package type has a tag id-display tuple. - */ - boolean hasTag(); - - /** - * Indicates whether this package type has a vendor id. - * @return True if this package type has a vendor id. - */ - boolean hasVendor(); - - /** - * Indicates whether this package type has a {@code min-tools-rev} attribute. - * @return True if this package type has a {@code min-tools-rev} attribute. - */ - boolean hasMinToolsRev(); - - /** - * Indicates whether this package type has a {@code min-platform-tools-rev} attribute. - * @return True if this package type has a {@code min-platform-tools-rev} attribute. - */ - boolean hasMinPlatformToolsRev(); -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDesc.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDesc.java deleted file mode 100644 index 5effda3a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDesc.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.IListDescription; -import com.android.sdklib.repository.License; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PreciseRevision; - -import java.io.File; - -/** - * {@link IPkgDesc} keeps information on individual SDK packages - * (both local or remote packages definitions.) - *
- * Packages have different attributes depending on their type. - *

- * To create a new {@link IPkgDesc}, use one of the package-specific constructors - * provided by {@code PkgDesc.Builder.newXxx()}. - *

- * To query packages capabilities, rely on {@link #getType()} and the {@code IPkgDesc.hasXxx()} - * methods provided by {@link IPkgDesc}. - */ -public interface IPkgDesc extends Comparable, IPkgCapabilities, IListDescription { - - /** - * Returns the type of the package. - * @return Returns one of the {@link PkgType} constants. - */ - @NonNull - PkgType getType(); - - /** - * Returns the list-display meta data of this package. - * @return The list-display data, if available, or null. - */ - @Nullable - String getListDisplay(); - - @Nullable - String getDescriptionShort(); - - @Nullable - String getDescriptionUrl(); - - @Nullable - License getLicense(); - - boolean isObsolete(); - - /** - * Returns the package's {@link FullRevision} or null. - * @return A non-null value if {@link #hasFullRevision()} is true; otherwise a null value. - */ - @Nullable - FullRevision getFullRevision(); - - /** - * Returns the package's {@link MajorRevision} or null. - * @return A non-null value if {@link #hasMajorRevision()} is true; otherwise a null value. - */ - @Nullable - MajorRevision getMajorRevision(); - - /** - * Returns the package's revision or null. This will come from the {@link FullRevision} or - * {@link MajorRevision}, with the precision set as appropriate. - * @return A representation of {@link #getMajorRevision()} or {@link #getFullRevision()}, - * depending on which one exists. - */ - @NonNull - PreciseRevision getPreciseRevision(); - - /** - * Returns the package's {@link AndroidVersion} or null. - * @return A non-null value if {@link #hasAndroidVersion()} is true; otherwise a null value. - */ - @Nullable - AndroidVersion getAndroidVersion(); - - /** - * Returns the package's path string or null. - *

- * For {@link PkgType#PKG_SYS_IMAGE}, the path is the system-image ABI.
- * For {@link PkgType#PKG_PLATFORM}, the path is the platform hash string.
- * For {@link PkgType#PKG_ADDON}, the path is the platform hash string.
- * For {@link PkgType#PKG_EXTRA}, the path is the extra-path string.
- * - * @return A non-null value if {@link #hasPath()} is true; otherwise a null value. - */ - @Nullable - String getPath(); - - /** - * Returns the package's tag id-display tuple or null. - * - * @return A non-null tag if {@link #hasTag()} is true; otherwise a null value. - */ - @Nullable - IdDisplay getTag(); - - /** - * Returns the package's vendor-id string or null. - * @return A non-null value if {@link #hasVendor()} is true; otherwise a null value. - */ - @Nullable - IdDisplay getVendor(); - - /** - * Returns the package's {@code min-tools-rev} or null. - * @return A non-null value if {@link #hasMinToolsRev()} is true; otherwise a null value. - */ - @Nullable - FullRevision getMinToolsRev(); - - /** - * Returns the package's {@code min-platform-tools-rev} or null. - * @return A non-null value if {@link #hasMinPlatformToolsRev()} is true; otherwise null. - */ - @Nullable - FullRevision getMinPlatformToolsRev(); - - /** - * Indicates whether this package descriptor is an update for the given - * existing descriptor. Preview versions are never considered updates for non- - * previews, and vice versa. - * - * @param existingDesc A non-null existing descriptor. - * @return True if this package is an update for the given one. - */ - boolean isUpdateFor(@NonNull IPkgDesc existingDesc); - - /** - * Indicates whether this package descriptor is an update for the given - * existing descriptor, using the given comparison method. - * - * @param existingDesc A non-null existing descriptor. - * @param previewComparison The {@link FullRevision.PreviewComparison} method to use - * when comparing the packages. - * @return True if this package is an update for the given one. - */ - boolean isUpdateFor(@NonNull IPkgDesc existingDesc, - @NonNull FullRevision.PreviewComparison previewComparison); - - /** - * Returns a stable string id that can be used to reference this package, including - * a suffix indicating that this package is a preview if it is. - */ - @NonNull - String getInstallId(); - - /** - * Returns a stable string id that can be used to reference this package, which - * excludes the preview suffix. - */ - String getBaseInstallId(); - - /** - * Returns the canonical location where such a package would be installed. - * @param sdkLocation The root of the SDK. - * @return the canonical location where such a package would be installed. - */ - @NonNull - File getCanonicalInstallFolder(@NonNull File sdkLocation); - - /** - * @return True if the revision of this package is a preview. - */ - boolean isPreview(); -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescAddon.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescAddon.java deleted file mode 100644 index 02c0ad5a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescAddon.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2014 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.repository.descriptors; - -import com.android.annotations.NonNull; - -/** - * {@link IPkgDescAddon} keeps information on individual add-on SDK packages - * (both local or remote packages definitions.) The base {@link IPkgDesc} tries - * to present a unified interface to package attributes and this interface - * adds methods specific to extras. - *

- * To create a new {@link IPkgDescAddon}, - * use {@link PkgDesc.Builder#newAddon(com.android.sdklib.AndroidVersion, com.android.sdklib.repository.MajorRevision, IdDisplay, IdDisplay)}. - *

- * To query generic packages capabilities, rely on {@link #getType()} and the - * {@code IPkgDesc.hasXxx()} methods provided by {@link IPkgDesc}. - */ -public interface IPkgDescAddon extends IPkgDesc { - - /** - * Returns the id/display name of the add-on. - * @return A non-null id/display name for the add-on - */ - @NonNull IdDisplay getName(); -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescExtra.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescExtra.java deleted file mode 100644 index 68c4bd72..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IPkgDescExtra.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.annotations.NonNull; -import com.android.sdklib.repository.NoPreviewRevision; - -/** - * {@link IPkgDescExtra} keeps information on individual extra SDK packages - * (both local or remote packages definitions.) The base {@link IPkgDesc} tries - * to present a unified interface to package attributes and this interface - * adds methods specific to extras. - *

- * To create a new {@link IPkgDescExtra}, - * use {@link PkgDesc.Builder#newExtra(IdDisplay, String, String, String[], NoPreviewRevision)}. - *

- * The extra's revision is a {@link NoPreviewRevision}; the attribute is however - * accessed via {@link IPkgDesc#getFullRevision()} instead of introducing a new - * custom method. - *

- * To query generic packages capabilities, rely on {@link #getType()} and the - * {@code IPkgDesc.hasXxx()} methods provided by {@link IPkgDesc}. - */ -public interface IPkgDescExtra extends IPkgDesc { - /** - * Returns an optional list of older paths for this extra package. - * @return A non-null, possibly empty, for old paths previously used for the same extra. - */ - @NonNull String[] getOldPaths(); - - /** - * Returns the display name of the Extra. - * @return A non-null name for the Extra, used for display purposes. - */ - @NonNull String getNameDisplay(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IdDisplay.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IdDisplay.java deleted file mode 100644 index 0278ba5b..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/IdDisplay.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2014 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.repository.descriptors; - -import com.android.annotations.NonNull; - -/** - * Immutable structure that represents a tuple (id-string + display-string.) - */ -public final class IdDisplay implements Comparable { - - private final String mId; - private final String mDisplay; - - /** - * Creates a new immutable tuple (id-string + display-string.) - * - * @param id The non-null id string. - * @param display The non-null display string. - */ - public IdDisplay(@NonNull String id, @NonNull String display) { - mId = id; - mDisplay = display; - } - - @NonNull - public String getId() { - return mId; - } - - @NonNull - public String getDisplay() { - return mDisplay; - } - - /** - * {@link IdDisplay} instances are the same if they have the same id. - * The display value is not used for comparison or ordering. - */ - @Override - public int compareTo(IdDisplay tag) { - return mId.compareTo(tag.mId); - } - - /** - * Hash code of {@link IdDisplay} instances only rely on the id hash code. - */ - @Override - public int hashCode() { - return mId.hashCode(); - } - - /** - * Equality of {@link IdDisplay} instances only rely on the id equality. - * The display value is not used for comparison or ordering. - */ - @Override - public boolean equals(Object obj) { - return (obj instanceof IdDisplay) && mId.equals(((IdDisplay)obj).mId); - } - - /** - * Returns a string representation for *debug* purposes only, not for UI display. - */ - @Override - public String toString() { - return String.format("%1$s [%2$s]", mId, mDisplay); - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDesc.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDesc.java deleted file mode 100644 index eda9838d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDesc.java +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.SystemImage; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdklib.repository.License; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.PreciseRevision; - -import java.io.File; -import java.util.Locale; - -/** - * {@link PkgDesc} keeps information on individual SDK packages - * (both local or remote packages definitions.) - *
- * Packages have different attributes depending on their type. - *

- * To create a new {@link PkgDesc}, use one of the package-specific constructors - * provided here. - *

- * To query packages capabilities, rely on {@link #getType()} and the {@code PkgDesc.hasXxx()} - * methods provided in the base {@link PkgDesc}. - */ -public class PkgDesc implements IPkgDesc { - public static final String PREVIEW_SUFFIX = "-preview"; - private final PkgType mType; - private final FullRevision mFullRevision; - private final MajorRevision mMajorRevision; - private final AndroidVersion mAndroidVersion; - private final String mPath; - private final IdDisplay mTag; - private final IdDisplay mVendor; - private final FullRevision mMinToolsRev; - private final FullRevision mMinPlatformToolsRev; - private final IIsUpdateFor mCustomIsUpdateFor; - private final IGetPath mCustomPath; - - private final License mLicense; - private final String mListDisplay; - private final String mDescriptionShort; - private final String mDescriptionUrl; - private final boolean mIsObsolete; - - protected PkgDesc(@NonNull PkgType type, - @Nullable License license, - @Nullable String listDisplay, - @Nullable String descriptionShort, - @Nullable String descriptionUrl, - boolean isObsolete, - @Nullable FullRevision fullRevision, - @Nullable MajorRevision majorRevision, - @Nullable AndroidVersion androidVersion, - @Nullable String path, - @Nullable IdDisplay tag, - @Nullable IdDisplay vendor, - @Nullable FullRevision minToolsRev, - @Nullable FullRevision minPlatformToolsRev, - @Nullable IIsUpdateFor customIsUpdateFor, - @Nullable IGetPath customPath) { - mType = type; - mIsObsolete = isObsolete; - mLicense = license; - mListDisplay = listDisplay; - mDescriptionShort = descriptionShort; - mDescriptionUrl = descriptionUrl; - mFullRevision = fullRevision; - mMajorRevision = majorRevision; - mAndroidVersion = androidVersion; - mPath = path; - mTag = tag; - mVendor = vendor; - mMinToolsRev = minToolsRev; - mMinPlatformToolsRev = minPlatformToolsRev; - mCustomIsUpdateFor = customIsUpdateFor; - mCustomPath = customPath; - } - - @NonNull - @Override - public PkgType getType() { - return mType; - } - - @Override - @Nullable - public String getListDisplay() { - return mListDisplay; - } - - @Override - @Nullable - public String getDescriptionShort() { - return mDescriptionShort; - } - - @Override - @Nullable - public String getDescriptionUrl() { - return mDescriptionUrl; - } - - @Override - @Nullable - public License getLicense() { - return mLicense; - } - - @Override - public boolean isObsolete() { - return mIsObsolete; - } - - @Override - public final boolean hasFullRevision() { - return getType().hasFullRevision(); - } - - @Override - public final boolean hasMajorRevision() { - return getType().hasMajorRevision(); - } - - @Override - public final boolean hasAndroidVersion() { - return getType().hasAndroidVersion(); - } - - @Override - public final boolean hasPath() { - return getType().hasPath(); - } - - @Override - public final boolean hasTag() { - return getType().hasTag(); - } - - @Override - public boolean hasVendor() { - return getType().hasVendor(); - } - - @Override - public final boolean hasMinToolsRev() { - return getType().hasMinToolsRev(); - } - - @Override - public final boolean hasMinPlatformToolsRev() { - return getType().hasMinPlatformToolsRev(); - } - - @Nullable - @Override - public FullRevision getFullRevision() { - return mFullRevision; - } - - @Nullable - @Override - public MajorRevision getMajorRevision() { - return mMajorRevision; - } - - @NonNull - @Override - public final PreciseRevision getPreciseRevision() { - if (mMajorRevision == null) { - return new PreciseRevision(mFullRevision.getMajor(), mFullRevision.getMinor(), - mFullRevision.getMicro(), mFullRevision.getPreview()); - } - return new PreciseRevision(mMajorRevision.getMajor()); - } - - @Nullable - @Override - public AndroidVersion getAndroidVersion() { - return mAndroidVersion; - } - - @Override - public boolean isPreview() { - return getPreciseRevision().isPreview(); - } - - @Nullable - @Override - public String getPath() { - if (mCustomPath != null) { - return mCustomPath.getPath(this); - } else { - return mPath; - } - } - - @Nullable - @Override - public IdDisplay getTag() { - return mTag; - } - - @Nullable - @Override - public IdDisplay getVendor() { - return mVendor; - } - - @Nullable - @Override - public FullRevision getMinToolsRev() { - return mMinToolsRev; - } - - @Nullable - @Override - public FullRevision getMinPlatformToolsRev() { - return mMinPlatformToolsRev; - } - - @Override - public String getInstallId() { - String id = getBaseInstallId(); - if (getPreciseRevision().isPreview()) { - return id + PREVIEW_SUFFIX; - } - return id; - } - - @Override - public String getBaseInstallId() { - StringBuilder sb = new StringBuilder(); - - /* iid patterns: - tools, platform-tools => FOLDER - build-tools => FOLDER-REV - doc, sample, source => ENUM-API - extra => ENUM-VENDOR.id-PATH - platform => android-API - add-on => addon-NAME.id-VENDOR.id-API - platform sys-img => sys-img-ABI-TAG|android-API - add-on sys-img => sys-img-ABI-addon-NAME.id-VENDOR.id-API - */ - - switch (mType) { - case PKG_TOOLS: - case PKG_PLATFORM_TOOLS: - sb.append(mType.getFolderName()); - break; - - case PKG_BUILD_TOOLS: - sb.append(mType.getFolderName()).append('-'); - // Add version number without the preview revision number. This is to make preview - // packages be updatable to the next revision. - int[] version = getPreciseRevision().toIntArray(false); - for (int i = 0; i < version.length; i++) { - sb.append(version[i]); - if (i != version.length - 1) { - sb.append('.'); - } - } - break; - - case PKG_DOC: - sb.append("doc"); - break; - - case PKG_SAMPLE: - case PKG_SOURCE: - sb.append(mType.toString().toLowerCase(Locale.US).replace("pkg_", "")); - sb.append('-').append(getAndroidVersion().getApiString()); - break; - - case PKG_EXTRA: - sb.append("extra-") - .append(getVendor().getId()) - .append('-') - .append(getPath()); - break; - - case PKG_PLATFORM: - sb.append(AndroidTargetHash.PLATFORM_HASH_PREFIX) - .append(getAndroidVersion().getApiString()); - break; - - case PKG_ADDON: - sb.append("addon-") - .append(((IPkgDescAddon)this).getName().getId()) - .append('-') - .append(getVendor().getId()) - .append('-') - .append(getAndroidVersion().getApiString()); - break; - - case PKG_SYS_IMAGE: - sb.append("sys-img-") - .append(getPath()) // path==ABI for sys-img - .append('-') - .append(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId()) - .append('-') - .append(getAndroidVersion().getApiString()); - break; - - case PKG_ADDON_SYS_IMAGE: - sb.append("sys-img-") - .append(getPath()) // path==ABI for sys-img - .append("-addon-") - .append(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId()) - .append('-') - .append(getVendor().getId()) - .append('-') - .append(getAndroidVersion().getApiString()); - break; - - case PKG_NDK: - sb.append("ndk"); - break; - - default: - throw new IllegalArgumentException("IID not defined for type " + mType.toString()); - } - - return sanitize(sb.toString()); - } - - @Override - public File getCanonicalInstallFolder(@NonNull File sdkLocation) { - File f = LegacyFileOp.append(sdkLocation, mType.getFolderName()); - - /* folder patterns: - tools, platform-tools, doc => FOLDER - build-tools, add-on => FOLDER/IID - platform, sample, source => FOLDER/android-API - platform sys-img => FOLDER/android-API/TAG/ABI - add-on sys-img => FOLDER/addon-NAME.id-VENDOR.id-API/ABI - extra => FOLDER/VENDOR.id/PATH - */ - - switch (mType) { - case PKG_TOOLS: - case PKG_PLATFORM_TOOLS: - case PKG_DOC: - // no-op, top-folder is all what is needed here - break; - - case PKG_BUILD_TOOLS: - case PKG_ADDON: - f = LegacyFileOp.append(f, getInstallId()); - break; - - case PKG_PLATFORM: - case PKG_SAMPLE: - case PKG_SOURCE: - f = LegacyFileOp.append(f, AndroidTargetHash.PLATFORM_HASH_PREFIX + sanitize( - getAndroidVersion().getApiString())); - break; - - case PKG_SYS_IMAGE: - f = LegacyFileOp.append(f, - AndroidTargetHash.PLATFORM_HASH_PREFIX + sanitize( - getAndroidVersion().getApiString()), - sanitize(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" - : getTag().getId()), - sanitize(getPath())); // path==abi - break; - - case PKG_ADDON_SYS_IMAGE: - String name = "addon-" - + (SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId()) - + '-' - + getVendor().getId() - + '-' - + getAndroidVersion().getApiString(); - f = LegacyFileOp.append(f, - sanitize(name), - sanitize(getPath())); // path==abi - break; - - case PKG_EXTRA: - f = LegacyFileOp.append(f, - sanitize(getVendor().getId()), - sanitize(getPath())); - break; - - default: - throw new IllegalArgumentException( - "CanonicalFolder not defined for type " + mType.toString()); - } - - return f; - } - - //---- Updating ---- - - /** - * Computes the most general case of {@link #isUpdateFor(IPkgDesc)}. - * Individual package types use this and complement with their own specific cases - * as needed. - * - * @param existingDesc A non-null package descriptor to compare with. - * @return True if this package descriptor would generally update the given one. - */ - @Override - public boolean isUpdateFor(@NonNull IPkgDesc existingDesc) { - return isUpdateFor(existingDesc, PreviewComparison.COMPARE_NUMBER); - } - - @Override - public boolean isUpdateFor(@NonNull IPkgDesc existingDesc, - @NonNull PreviewComparison previewComparison) { - if (mCustomIsUpdateFor != null) { - return mCustomIsUpdateFor.isUpdateFor(this, existingDesc); - } else { - return isGenericUpdateFor(existingDesc, previewComparison); - } - } - - /** - * Computes the most general case of {@link #isUpdateFor(IPkgDesc)}. - * Individual package types use this and complement with their own specific cases - * as needed. - * - * @param existingDesc A non-null package descriptor to compare with. - * @param previewComparison The type of preview comparison to do. - * @return True if this package descriptor would generally update the given one. - */ - private boolean isGenericUpdateFor(@NonNull IPkgDesc existingDesc, - PreviewComparison previewComparison) { - - if (existingDesc == null || !getType().equals(existingDesc.getType())) { - return false; - } - - // Packages that have an Android version can generally only be updated - // for the same Android version (otherwise it's a new artifact.) - if (hasAndroidVersion() && !getAndroidVersion().equals(existingDesc.getAndroidVersion())) { - return false; - } - - // Packages that have a vendor id need the same vendor id on both sides - if (hasVendor() && !getVendor().equals(existingDesc.getVendor())) { - return false; - } - - // Packages that have a tag id need the same tag id on both sides - if (hasTag() && !getTag().getId().equals(existingDesc.getTag().getId())) { - return false; - } - - // Packages that have a path can generally only be updated if both use the same path - if (hasPath()) { - if (this instanceof IPkgDescExtra) { - // Extra package handle paths differently, they need to use the old_path - // to allow upgrade compatibility. - if (!PkgDescExtra.compatibleVendorAndPath((IPkgDescExtra) this, - (IPkgDescExtra) existingDesc)) { - return false; - } - } else if (!getPath().equals(existingDesc.getPath())) { - return false; - } - } - - // Packages that have a major version are generally updates if it increases. - if (hasMajorRevision() && - getMajorRevision().compareTo(existingDesc.getMajorRevision()) > 0) { - return true; - } - - // Packages that have a full revision are generally updates if it increases - // but keeps the same kind of preview (e.g. previews are only updates by previews.) - if (hasFullRevision() && - (previewComparison == PreviewComparison.IGNORE - || existingDesc.isPreview() == isPreview())) { - // If both packages match in their preview type (both previews or both not previews) - // then is the RC/preview number an update? - return getFullRevision().compareTo(existingDesc.getFullRevision(), - PreviewComparison.COMPARE_NUMBER) > 0; - } - - return false; - } - - - //---- Ordering ---- - - /** - * Compares this descriptor to another one. - * All fields must match for equality. - *

- * This is must not be used an indication that a package is a suitable update for another one. - * The comparison order is however suitable for sorting packages for display purposes. - */ - @Override - public int compareTo(@NonNull IPkgDesc o) { - int t1 = getType().getIntValue(); - int t2 = o.getType().getIntValue(); - if (t1 != t2) { - return t1 - t2; - } - - if (hasAndroidVersion() && o.hasAndroidVersion()) { - t1 = getAndroidVersion().compareTo(o.getAndroidVersion()); - if (t1 != 0) { - return t1; - } - } - - if (hasVendor() && o.hasVendor()) { - t1 = getVendor().compareTo(o.getVendor()); - if (t1 != 0) { - return t1; - } - } - - if (hasTag() && o.hasTag()) { - t1 = getTag().compareTo(o.getTag()); - if (t1 != 0) { - return t1; - } - } - - if (hasPath() && o.hasPath()) { - t1 = getPath().compareTo(o.getPath()); - if (t1 != 0) { - return t1; - } - } - - if (hasFullRevision() && o.hasFullRevision()) { - t1 = getFullRevision().compareTo(o.getFullRevision()); - if (t1 != 0) { - return t1; - } - } - - if (hasMajorRevision() && o.hasMajorRevision()) { - t1 = getMajorRevision().compareTo(o.getMajorRevision()); - if (t1 != 0) { - return t1; - } - } - - if (hasMinToolsRev() && o.hasMinToolsRev()) { - t1 = getMinToolsRev().compareTo(o.getMinToolsRev()); - if (t1 != 0) { - return t1; - } - } - - if (hasMinPlatformToolsRev() && o.hasMinPlatformToolsRev()) { - t1 = getMinPlatformToolsRev().compareTo(o.getMinPlatformToolsRev()); - if (t1 != 0) { - return t1; - } - } - - return 0; - } - - // --- display description ---- - - @NonNull - @Override - public String getListDescription() { - if (mListDisplay != null && !mListDisplay.isEmpty()) { - return mListDisplay; - } - - return patternReplaceImpl(getType().getListDisplayPattern()); - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected String patternReplaceImpl(String result) { - // Flags for list description pattern string, used in PkgType: - // $MAJ $FULL $API $PATH $TAG $VEND $NAME (for extras) - - result = result - .replace("$MAJ", hasMajorRevision() ? getMajorRevision().toShortString() : ""); - result = result - .replace("$FULL", hasFullRevision() ? getFullRevision().toShortString() : ""); - result = result - .replace("$API", hasAndroidVersion() ? getAndroidVersion().getApiString() : ""); - result = result.replace("$PATH", hasPath() ? getPath() : ""); - result = result.replace("$TAG", hasTag() && !getTag().equals(SystemImage.DEFAULT_TAG) ? - getTag().getDisplay() : ""); - result = result.replace("$VEND", hasVendor() ? getVendor().getDisplay() : ""); - String name = ""; - if (this instanceof IPkgDescExtra) { - name = ((IPkgDescExtra) this).getNameDisplay(); - } else if (this instanceof IPkgDescAddon) { - name = ((IPkgDescAddon) this).getName().getDisplay(); - } - result = result.replace("$NAME", name); - - // Evaluate replacements. - // {|choice1|choice2|...|choiceN|} gets replaced by the first non-empty choice. - for (int start = result.indexOf("{|"); - start >= 0; - start = result.indexOf("{|")) { - int end = result.indexOf('}', start); - int last = start + 1; - for (int pipe = result.indexOf('|', last+1); - pipe > start; - last = pipe, pipe = result.indexOf('|', last+1)) { - if (pipe - last > 1) { - result = result.substring(0, start) + - result.substring(last+1, pipe) + - result.substring(end+1); - break; - } - } - } - - // Evaluate conditions. - // {?value>1:text to use} -- uses the text if value is greater than 1. - // Simplification: this is our only test right now so hard-code it instead of - // using a generic expression evaluation. - for (int start = result.indexOf("{?"); - start >= 0; - start = result.indexOf("{?")) { - int end = result.indexOf('}', start); - int op = result.indexOf(">1:"); - if (op > start) { - String value = ""; - try { - FullRevision i = FullRevision.parseRevision(result.substring(start+2, op)); - if (i.compareTo(new FullRevision(1)) > 0) { - value = result.substring(op+3, end); - } - } catch (NumberFormatException e) { - value = "ERROR " + e.getMessage() + " in " + result.substring(start, end+1); - } - result = result.substring(0, start) + - value + - result.substring(end+1); - } - } - - - return result; - } - - /** String representation for debugging purposes. */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("'); - return builder.toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (hasAndroidVersion() ? getAndroidVersion().hashCode() : 0); - result = prime * result + (hasVendor() ? getVendor() .hashCode() : 0); - result = prime * result + (hasTag() ? getTag() .hashCode() : 0); - result = prime * result + (hasPath() ? getPath() .hashCode() : 0); - result = prime * result + (hasFullRevision() ? getFullRevision() .hashCode() : 0); - result = prime * result + (hasMajorRevision() ? getMajorRevision() .hashCode() : 0); - result = prime * result + (hasMinToolsRev() ? getMinToolsRev() .hashCode() : 0); - result = prime * result + (hasMinPlatformToolsRev() ? - getMinPlatformToolsRev().hashCode() : 0); - - return result; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof IPkgDesc)) return false; - IPkgDesc rhs = (IPkgDesc) obj; - - if (hasAndroidVersion() != rhs.hasAndroidVersion()) { - return false; - } - if (hasAndroidVersion() && !getAndroidVersion().equals(rhs.getAndroidVersion())) { - return false; - } - - if (hasTag() != rhs.hasTag()) { - return false; - } - if (hasTag() && !getTag().equals(rhs.getTag())) { - return false; - } - - if (hasPath() != rhs.hasPath()) { - return false; - } - if (hasPath() && !getPath().equals(rhs.getPath())) { - return false; - } - - if (hasFullRevision() != rhs.hasFullRevision()) { - return false; - } - if (hasFullRevision() && !getFullRevision().equals(rhs.getFullRevision())) { - return false; - } - - if (hasMajorRevision() != rhs.hasMajorRevision()) { - return false; - } - if (hasMajorRevision() && !getMajorRevision().equals(rhs.getMajorRevision())) { - return false; - } - - if (hasMinToolsRev() != rhs.hasMinToolsRev()) { - return false; - } - if (hasMinToolsRev() && !getMinToolsRev().equals(rhs.getMinToolsRev())) { - return false; - } - - if (hasMinPlatformToolsRev() != rhs.hasMinPlatformToolsRev()) { - return false; - } - if (hasMinPlatformToolsRev() && - !getMinPlatformToolsRev().equals(rhs.getMinPlatformToolsRev())) { - return false; - } - - return true; - } - - - // ---- Constructors ----- - - public interface IIsUpdateFor { - boolean isUpdateFor(@NonNull PkgDesc thisPkgDesc, @NonNull IPkgDesc existingDesc); - } - - public interface IGetPath { - String getPath(@NonNull PkgDesc thisPkgDesc); - } - - public static class Builder { - private final PkgType mType; - private FullRevision mFullRevision; - private MajorRevision mMajorRevision; - private AndroidVersion mAndroidVersion; - private String mPath; - private IdDisplay mTag; - private IdDisplay mVendor; - private FullRevision mMinToolsRev; - private FullRevision mMinPlatformToolsRev; - private IIsUpdateFor mCustomIsUpdateFor; - private IGetPath mCustomPath; - private String[] mOldPaths; - private String mNameDisplay; - private IdDisplay mNameIdDisplay; - - private License mLicense; - private String mListDisplay; - private String mDescriptionShort; - private String mDescriptionUrl; - private boolean mIsObsolete; - - - private Builder(PkgType type) { - mType = type; - } - - /** - * Creates a new tool package descriptor. - * - * @param revision The revision of the tool package. - * @param minPlatformToolsRev The {@code min-platform-tools-rev}. - * Use {@link FullRevision#NOT_SPECIFIED} to indicate there is no requirement. - * @return A {@link PkgDesc} describing this tool package. - */ - @NonNull - public static Builder newTool(@NonNull FullRevision revision, - @NonNull FullRevision minPlatformToolsRev) { - Builder p = new Builder(PkgType.PKG_TOOLS); - p.mFullRevision = revision; - p.mMinPlatformToolsRev = minPlatformToolsRev; - return p; - } - - /** - * Creates a new platform-tool package descriptor. - * - * @param revision The revision of the platform-tool package. - * @return A {@link PkgDesc} describing this platform-tool package. - */ - @NonNull - public static Builder newPlatformTool(@NonNull FullRevision revision) { - Builder p = new Builder(PkgType.PKG_PLATFORM_TOOLS); - p.mFullRevision = revision; - return p; - } - - /** - * Creates a new build-tool package descriptor. - * - * @param revision The revision of the build-tool package. - * @return A {@link PkgDesc} describing this build-tool package. - */ - @NonNull - public static Builder newBuildTool(@NonNull FullRevision revision) { - Builder p = new Builder(PkgType.PKG_BUILD_TOOLS); - p.mFullRevision = revision; - p.mCustomIsUpdateFor = new IIsUpdateFor() { - @Override - public boolean isUpdateFor(PkgDesc thisPkgDesc, IPkgDesc existingDesc) { - // Generic test checks that the preview type is the same (both previews or not). - // Build tool is different in that the full revision must be an exact match - // and not an increase. - return thisPkgDesc - .isGenericUpdateFor(existingDesc, PreviewComparison.COMPARE_NUMBER) && - thisPkgDesc.getFullRevision().compareTo( - existingDesc.getFullRevision(), - PreviewComparison.COMPARE_TYPE) == 0; - } - }; - return p; - } - - /** - * Creates a new doc package descriptor. - * - * @param revision The revision of the doc package. - * @return A {@link PkgDesc} describing this doc package. - */ - @NonNull - public static Builder newDoc(@NonNull AndroidVersion version, - @NonNull MajorRevision revision) { - Builder p = new Builder(PkgType.PKG_DOC); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mCustomIsUpdateFor = new IIsUpdateFor() { - @Override - public boolean isUpdateFor(PkgDesc thisPkgDesc, IPkgDesc existingDesc) { - if (existingDesc == null || - !thisPkgDesc.getType().equals(existingDesc.getType())) { - return false; - } - - // This package is unique in the SDK. It's an update if the API is newer - // or the revision is newer for the same API. - int diff = thisPkgDesc.getAndroidVersion().compareTo( - existingDesc.getAndroidVersion()); - return diff > 0 || - (diff == 0 && thisPkgDesc.getMajorRevision().compareTo( - existingDesc.getMajorRevision()) > 0); - } - }; - return p; - } - - /** - * Creates a new extra package descriptor. - * - * @param vendor The vendor id string of the extra package. - * @param path The path id string of the extra package. - * @param displayName The display name. If missing, caller should build one using the path. - * @param oldPaths An optional list of older paths for this extra package. - * @param revision The revision of the extra package. - * @return A {@link PkgDesc} describing this extra package. - */ - @NonNull - public static Builder newExtra(@NonNull IdDisplay vendor, - @NonNull String path, - @Nullable String displayName, - @Nullable String[] oldPaths, - @NonNull NoPreviewRevision revision) { - Builder p = new Builder(PkgType.PKG_EXTRA); - p.mFullRevision = revision; - p.mVendor = vendor; - p.mPath = path; - p.mNameDisplay = displayName; - p.mOldPaths = oldPaths; - return p; - } - - /** - * Creates a new platform package descriptor. - * - * @param version The android version of the platform package. - * @param revision The revision of the extra package. - * @param minToolsRev An optional {@code min-tools-rev}. - * Use {@link FullRevision#NOT_SPECIFIED} to indicate - * there is no requirement. - * @return A {@link PkgDesc} describing this platform package. - */ - @NonNull - public static Builder newPlatform(@NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull FullRevision minToolsRev) { - Builder p = new Builder(PkgType.PKG_PLATFORM); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mMinToolsRev = minToolsRev; - p.mCustomPath = new IGetPath() { - @Override - public String getPath(PkgDesc thisPkgDesc) { - /** The "path" of a Platform is its Target Hash. */ - return AndroidTargetHash.getPlatformHashString(thisPkgDesc.getAndroidVersion()); - } - }; - return p; - } - - /** - * Create a new add-on package descriptor. - *

- * The vendor id and the name id provided are used to compute the add-on's - * target hash. - * - * @param version The android version of the add-on package. - * @param revision The revision of the add-on package. - * @param addonVendor The vendor id/display of the add-on package. - * @param addonName The name id/display of the add-on package. - * @return A {@link PkgDesc} describing this add-on package. - */ - @NonNull - public static Builder newAddon(@NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull IdDisplay addonVendor, - @NonNull IdDisplay addonName) { - Builder p = new Builder(PkgType.PKG_ADDON); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mVendor = addonVendor; - p.mNameIdDisplay = addonName; - return p; - } - - /** - * Create a new platform system-image package descriptor. - *

- * For system-images, {@link PkgDesc#getPath()} returns the ABI. - * - * @param version The android version of the system-image package. - * @param tag The tag of the system-image package. - * @param abi The ABI of the system-image package. - * @param revision The revision of the system-image package. - * @return A {@link PkgDesc} describing this system-image package. - */ - @NonNull - public static Builder newSysImg(@NonNull AndroidVersion version, - @NonNull IdDisplay tag, - @NonNull String abi, - @NonNull MajorRevision revision) { - Builder p = new Builder(PkgType.PKG_SYS_IMAGE); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mTag = tag; - p.mPath = abi; - p.mVendor = null; - return p; - } - - /** - * Create a new add-on system-image package descriptor. - *

- * For system-images, {@link PkgDesc#getPath()} returns the ABI. - * - * @param version The android version of the system-image package. - * @param addonVendor The vendor id/display of an associated add-on. - * @param addonName The tag of the system-image package is the add-on name. - * @param abi The ABI of the system-image package. - * @param revision The revision of the system-image package. - * @return A {@link PkgDesc} describing this system-image package. - */ - @NonNull - public static Builder newAddonSysImg(@NonNull AndroidVersion version, - @NonNull IdDisplay addonVendor, - @NonNull IdDisplay addonName, - @NonNull String abi, - @NonNull MajorRevision revision) { - Builder p = new Builder(PkgType.PKG_ADDON_SYS_IMAGE); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mTag = addonName; - p.mPath = abi; - p.mVendor = addonVendor; - return p; - } - - /** - * Create a new source package descriptor. - * - * @param version The android version of the source package. - * @param revision The revision of the source package. - * @return A {@link PkgDesc} describing this source package. - */ - @NonNull - public static Builder newSource(@NonNull AndroidVersion version, - @NonNull MajorRevision revision) { - Builder p = new Builder(PkgType.PKG_SOURCE); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - return p; - } - - /** - * Create a new sample package descriptor. - * - * @param version The android version of the sample package. - * @param revision The revision of the sample package. - * @param minToolsRev An optional {@code min-tools-rev}. - * Use {@link FullRevision#NOT_SPECIFIED} to indicate - * there is no requirement. - * @return A {@link PkgDesc} describing this sample package. - */ - @NonNull - public static Builder newSample(@NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull FullRevision minToolsRev) { - Builder p = new Builder(PkgType.PKG_SAMPLE); - p.mAndroidVersion = version; - p.mMajorRevision = revision; - p.mMinToolsRev = minToolsRev; - return p; - } - - /** - * Creates a new NDK package descriptor. - * - * @param revision The revision of the NDK package. - * @return A {@link PkgDesc} describing this NDK package. - */ - @NonNull - public static Builder newNdk(@NonNull FullRevision revision) { - Builder p = new Builder(PkgType.PKG_NDK); - p.mFullRevision = revision; - return p; - } - - public Builder setLicense(@Nullable License license) { - mLicense = license; - return this; - } - - public Builder setListDisplay(@Nullable String text) { - mListDisplay = text; - return this; - } - - public Builder setDescriptionShort(@Nullable String text) { - mDescriptionShort = text; - return this; - } - - public Builder setDescriptionUrl(@Nullable String text) { - mDescriptionUrl = text; - return this; - } - - public Builder setIsObsolete(boolean isObsolete) { - mIsObsolete = isObsolete; - return this; - } - - public IPkgDesc create() { - if (mType == PkgType.PKG_ADDON) { - return new PkgDescAddon( - mType, - mLicense, - mListDisplay, - mDescriptionShort, - mDescriptionUrl, - mIsObsolete, - mMajorRevision, - mAndroidVersion, - mVendor, - mNameIdDisplay); - } - - if (mType == PkgType.PKG_EXTRA) { - return new PkgDescExtra( - mType, - mLicense, - mListDisplay, - mDescriptionShort, - mDescriptionUrl, - mIsObsolete, - mFullRevision, - mMajorRevision, - mAndroidVersion, - mPath, - mTag, - mVendor, - mMinToolsRev, - mMinPlatformToolsRev, - mNameDisplay, - mOldPaths); - } - - return new PkgDesc( - mType, - mLicense, - mListDisplay, - mDescriptionShort, - mDescriptionUrl, - mIsObsolete, - mFullRevision, - mMajorRevision, - mAndroidVersion, - mPath, - mTag, - mVendor, - mMinToolsRev, - mMinPlatformToolsRev, - mCustomIsUpdateFor, - mCustomPath); - } - } - - // ---- Helpers ----- - - @NonNull - private static String sanitize(@NonNull String str) { - str = str.toLowerCase(Locale.US).replaceAll("[^a-z0-9_.-]+", "_").replaceAll("_+", "_"); - return str; - } -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescAddon.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescAddon.java deleted file mode 100644 index 9694d1f8..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescAddon.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.License; -import com.android.sdklib.repository.MajorRevision; - -/** - * Implementation detail of {@link PkgDesc} for add-ons. - * Do not use this class directly. - * To create an instance use {@link PkgDesc.Builder#newAddon} instead. - */ -final class PkgDescAddon extends PkgDesc implements IPkgDescAddon { - - private final IdDisplay mAddonName; - - /** - * Add-on descriptor. - * The following attributes are mandatory: - */ - PkgDescAddon(@NonNull PkgType type, - @Nullable License license, - @Nullable String listDisplay, - @Nullable String descriptionShort, - @Nullable String descriptionUrl, - boolean isObsolete, - @NonNull MajorRevision majorRevision, - @NonNull AndroidVersion androidVersion, - @NonNull IdDisplay addonVendor, - @NonNull IdDisplay addonName) { - super(type, - license, - listDisplay, - descriptionShort, - descriptionUrl, - isObsolete, - null, //fullRevision - majorRevision, - androidVersion, - AndroidTargetHash.getAddonHashString(addonVendor.getDisplay(), - addonName.getDisplay(), - androidVersion), - null, //tag - addonVendor, - null, //minToolsRev - null, //minPlatformToolsRev - null, //customIsUpdateFor - null); //customPath - - mAddonName = addonName; - } - - @NonNull - @Override - public IdDisplay getName() { - return mAddonName; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescExtra.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescExtra.java deleted file mode 100644 index b5f2efbf..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgDescExtra.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.License; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; - -/** - * Implementation detail of {@link IPkgDescExtra} for extra packages. - */ -public final class PkgDescExtra extends PkgDesc implements IPkgDescExtra { - - private final String[] mOldPaths; - private final String mNameDisplay; - - PkgDescExtra(@NonNull PkgType type, - @Nullable License license, - @Nullable String listDisplay, - @Nullable String descriptionShort, - @Nullable String descriptionUrl, - boolean isObsolete, - @Nullable FullRevision fullRevision, - @Nullable MajorRevision majorRevision, - @Nullable AndroidVersion androidVersion, - @Nullable String path, - @Nullable IdDisplay tag, - @Nullable IdDisplay vendor, - @Nullable FullRevision minToolsRev, - @Nullable FullRevision minPlatformToolsRev, - @Nullable String nameDisplay, - @Nullable final String[] oldPaths) { - super(type, - license, - listDisplay, - descriptionShort, - descriptionUrl, - isObsolete, - fullRevision, - majorRevision, - androidVersion, - path, - tag, - vendor, - minToolsRev, - minPlatformToolsRev, - null, //customIsUpdateFor - null); //customPath - mNameDisplay = nameDisplay; - mOldPaths = oldPaths != null ? oldPaths : new String[0]; - } - - @NonNull - @Override - public String[] getOldPaths() { - return mOldPaths; - } - - @NonNull - @Override - public String getNameDisplay() { - return mNameDisplay == null ? String.format("Unknown (%s)", getInstallId()) : mNameDisplay; - } - - // ---- Helpers ---- - - /** - * Helper method that converts the old_paths property string into the - * an old paths array. - * - * @param oldPathsProperty A possibly-null old_path property string. - * @return A list of old paths split by their separator. Can be empty but not null. - */ - @NonNull - public static String[] convertOldPaths(@Nullable String oldPathsProperty) { - if (oldPathsProperty == null || oldPathsProperty.isEmpty()) { - return new String[0]; - } - return oldPathsProperty.split(";"); //$NON-NLS-1$ - } - - /** - * Helper to computhe whether the extra path of both {@link IPkgDescExtra}s - * are compatible with each other, which means they are either equal or are - * matched between existing path and the potential old paths list. - *

- * This also covers backward compatibility -- in earlier schemas the vendor id was - * merged into the path string when reloading installed extras. - * - * @param lhs A non-null {@link IPkgDescExtra}. - * @param rhs Another non-null {@link IPkgDescExtra}. - * @return true if the paths are compatible. - */ - public static boolean compatibleVendorAndPath( - @NonNull IPkgDescExtra lhs, - @NonNull IPkgDescExtra rhs) { - String[] epOldPaths = rhs.getOldPaths(); - int lenEpOldPaths = epOldPaths.length; - for (int indexEp = -1; indexEp < lenEpOldPaths; indexEp++) { - if (sameVendorAndPath( - lhs.getVendor().getId(), lhs.getPath(), - rhs.getVendor().getId(), indexEp < 0 ? rhs.getPath() : epOldPaths[indexEp])) { - return true; - } - } - - String[] thisOldPaths = lhs.getOldPaths(); - int lenThisOldPaths = thisOldPaths.length; - for (int indexThis = -1; indexThis < lenThisOldPaths; indexThis++) { - if (sameVendorAndPath( - lhs.getVendor().getId(), indexThis < 0 ? lhs.getPath() : thisOldPaths[indexThis], - rhs.getVendor().getId(), rhs.getPath())) { - return true; - } - } - - return false; - } - - private static boolean sameVendorAndPath( - @Nullable String thisVendor, @Nullable String thisPath, - @Nullable String otherVendor, @Nullable String otherPath) { - // To be backward compatible, we need to support the old vendor-path form - // in either the current or the remote package. - // - // The vendor test below needs to account for an old installed package - // (e.g. with an install path of vendor-name) that has then been updated - // in-place and thus when reloaded contains the vendor name in both the - // path and the vendor attributes. - if (otherPath != null && thisPath != null && thisVendor != null) { - if (otherPath.equals(thisVendor + '-' + thisPath) && - (otherVendor == null || - otherVendor.isEmpty() || - otherVendor.equals(thisVendor))) { - return true; - } - } - if (thisPath != null && otherPath != null && otherVendor != null) { - if (thisPath.equals(otherVendor + '-' + otherPath) && - (thisVendor == null || - thisVendor.isEmpty() || - thisVendor.equals(otherVendor))) { - return true; - } - } - - - if (thisPath != null && thisPath.equals(otherPath)) { - if ((thisVendor == null && otherVendor == null) || - (thisVendor != null && thisVendor.equals(otherVendor))) { - return true; - } - } - - return false; - } - -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgType.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgType.java deleted file mode 100644 index 9f0ccc27..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/descriptors/PkgType.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.descriptors; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.LocalSdkParser; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.local.LocalSdk; - -import java.util.EnumSet; - -/** - * Package types handled by the {@link LocalSdk}. - *

- * Integer bit values are provided via {@link #getIntValue()} for backward - * compatibility with the older {@link LocalSdkParser} class. - * The integer bit values also indicate the natural ordering of the packages. - */ -public enum PkgType implements IPkgCapabilities { - - // Boolean attributes below, in that order: - // maj-r, full-r, api, path, tag, vend, min-t-r, min-pt-r - // - // Corresponding flags for list description pattern string: - // $MAJ $FULL $API $PATH $TAG $VEND $NAME (for extras & add-ons) - // - // - - /** Filter the SDK/tools folder. - * Has {@link FullRevision}. */ - PKG_TOOLS(0x0001, SdkConstants.FD_TOOLS, - "Android SDK Tools $FULL", - false, true /*full-r*/, false, false, false, false, false, true /*min-pt-r*/), - - /** Filter the SDK/platform-tools folder. - * Has {@link FullRevision}. */ - PKG_PLATFORM_TOOLS(0x0002, SdkConstants.FD_PLATFORM_TOOLS, - "Android SDK Platform-Tools $FULL", - false, true /*full-r*/, false, false, false, false, false, false), - - /** Filter the SDK/build-tools folder. - * Has {@link FullRevision}. */ - PKG_BUILD_TOOLS(0x0004, SdkConstants.FD_BUILD_TOOLS, - "Android SDK Build-Tools $FULL", - false, true /*full-r*/, false, false, false, false, false, false), - - /** Filter the SDK/docs folder. - * Has {@link MajorRevision}. */ - PKG_DOC(0x0010, SdkConstants.FD_DOCS, - "Documentation for Android SDK", - true /*maj-r*/, false, true /*api*/, false, false, false, false, false), - - /** Filter the SDK/platforms. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. - * Path returns the platform's target hash. */ - PKG_PLATFORM(0x0100, SdkConstants.FD_PLATFORMS, - "Android SDK Platform $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, true /*path*/, false, false, true /*min-t-r*/, false), - - /** Filter the SDK/system-images/android. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. Has tag. - * Path returns the system image ABI. */ - PKG_SYS_IMAGE(0x0200, SdkConstants.FD_SYSTEM_IMAGES, - "$PATH System Image, Android $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, true /*path*/, true /*tag*/, false /*vend*/, false, false), - - /** Filter the SDK/addons. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. - * Path returns the add-on's target hash. */ - PKG_ADDON(0x0400, SdkConstants.FD_ADDONS, - "{|$NAME|$VEND $PATH|}, Android $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, true /*path*/, false, true /*vend*/, false, false), - - /** Filter the SDK/system-images/addons. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. Has tag. - * Path returns the system image ABI. */ - PKG_ADDON_SYS_IMAGE(0x0800, SdkConstants.FD_SYSTEM_IMAGES, - "{|$NAME|$VEND $PATH|} System Image, Android $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, true /*path*/, true /*tag*/, true /*vend*/, false, false), - - /** Filter the SDK/samples folder. - * Note: this will not detect samples located in the SDK/extras packages. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. */ - PKG_SAMPLE(0x1000, SdkConstants.FD_SAMPLES, - "Samples for Android $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, false, false, false, true /*min-t-r*/, false), - - /** Filter the SDK/sources folder. - * Has {@link AndroidVersion}. Has {@link MajorRevision}. */ - PKG_SOURCE(0x2000, SdkConstants.FD_ANDROID_SOURCES, - "Sources for Android $API{?$MAJ>1:, rev $MAJ}", - true /*maj-r*/, false, true /*api*/, false, false, false, false, false), - - /** Filter the SDK/extras folder. - * Has {@code Path}. Has {@link MajorRevision}. - * Path returns the combined vendor id + extra path. - * Cast the descriptor to {@link IPkgDescExtra} to get extra's specific attributes. */ - PKG_EXTRA(0x4000, SdkConstants.FD_EXTRAS, - "{|$NAME|$VEND $PATH|}{?$FULL>1:, rev $FULL}", - false, true /*full-r*/, false, true /*path*/, false, true /*vend*/, false, false), - - /** The SDK/ndk folder. */ - PKG_NDK(0x8000, SdkConstants.FD_NDK, "", - false, true, false, false, false, false, false, false); - - /** A collection of all the known PkgTypes. */ - public static final EnumSet PKG_ALL = EnumSet.allOf(PkgType.class); - - /** Integer value matching all available pkg types, for the old LocalSdkParer. */ - public static final int PKG_ALL_INT = 0xFFFF; - - private int mIntValue; - private String mFolderName; - - private final boolean mHasMajorRevision; - private final boolean mHasFullRevision; - private final boolean mHasAndroidVersion; - private final boolean mHasPath; - private final boolean mHasTag; - private final boolean mHasVendor; - private final boolean mHasMinToolsRev; - private final boolean mHasMinPlatformToolsRev; - private final String mListDisplayPattern; - - PkgType(int intValue, - @NonNull String folderName, - @NonNull String listDisplayPattern, - boolean hasMajorRevision, - boolean hasFullRevision, - boolean hasAndroidVersion, - boolean hasPath, - boolean hasTag, - boolean hasVendor, - boolean hasMinToolsRev, - boolean hasMinPlatformToolsRev) { - mIntValue = intValue; - mFolderName = folderName; - mListDisplayPattern = listDisplayPattern; - mHasMajorRevision = hasMajorRevision; - mHasFullRevision = hasFullRevision; - mHasAndroidVersion = hasAndroidVersion; - mHasPath = hasPath; - mHasTag = hasTag; - mHasVendor = hasVendor; - mHasMinToolsRev = hasMinToolsRev; - mHasMinPlatformToolsRev = hasMinPlatformToolsRev; - } - - /** Returns the integer value matching the type, compatible with the old LocalSdkParer. */ - public int getIntValue() { - return mIntValue; - } - - /** Returns the name of SDK top-folder where this type of package is stored. */ - @NonNull - public String getFolderName() { - return mFolderName; - } - - @Override - public boolean hasMajorRevision() { - return mHasMajorRevision; - } - - @Override - public boolean hasFullRevision() { - return mHasFullRevision; - } - - @Override - public boolean hasAndroidVersion() { - return mHasAndroidVersion; - } - - @Override - public boolean hasPath() { - return mHasPath; - } - - @Override - public boolean hasTag() { - return mHasTag; - } - - @Override - public boolean hasVendor() { - return mHasVendor; - } - - @Override - public boolean hasMinToolsRev() { - return mHasMinToolsRev; - } - - @Override - public boolean hasMinPlatformToolsRev() { - return mHasMinPlatformToolsRev; - } - - /* - * Returns a pattern string used by {@link PkgDesc#getListDescription()} to - * compute a default list-display representation string for this package. - */ - public String getListDisplayPattern() { - return mListDisplayPattern; - } -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonPkgInfo.java deleted file mode 100644 index bce325e2..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonPkgInfo.java +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.ISystemImage.LocationType; -import com.android.sdklib.SystemImage; -import com.android.sdklib.internal.androidTarget.AddOnTarget; -import com.android.sdklib.internal.androidTarget.PlatformTarget; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.AddonManifestIniProps; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.descriptors.*; -import com.android.utils.Pair; -import com.google.common.base.Objects; -import com.google.common.collect.SetMultimap; -import com.google.common.collect.TreeMultimap; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@SuppressWarnings("MethodMayBeStatic") -public class LocalAddonPkgInfo extends LocalPlatformPkgInfo { - - private static final Pattern PATTERN_LIB_DATA = Pattern.compile( - "^([a-zA-Z0-9._-]+\\.jar);(.*)$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ - - // usb ids are 16-bit hexadecimal values. - private static final Pattern PATTERN_USB_IDS = Pattern.compile( - "^0x[a-f0-9]{4}$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ - - @NonNull - private final IPkgDescAddon mAddonDesc; - - public LocalAddonPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull IdDisplay vendor, - @NonNull IdDisplay name) { - super(localSdk, localDir, sourceProps, version, revision, FullRevision.NOT_SPECIFIED); - mAddonDesc = (IPkgDescAddon) PkgDesc.Builder.newAddon(version, revision, vendor, name) - .create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mAddonDesc; - } - - /** The "path" of an add-on is its Target Hash. */ - @Override - @NonNull - public String getTargetHash() { - return getDesc().getPath(); - } - - //----- - - /** - * Computes a sanitized name-id based on an addon name-display. - * This is used to provide compatibility with older add-ons that lacks the new fields. - * - * @param displayName A name-display field or a old-style name field. - * @return A non-null sanitized name-id that fits in the {@code [a-zA-Z0-9_-]+} pattern. - */ - public static String sanitizeDisplayToNameId(@NonNull String displayName) { - String name = displayName.toLowerCase(Locale.US); - name = name.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - name = name.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ - - // Trim leading and trailing underscores - if (name.length() > 1) { - name = name.replaceAll("^_+", ""); //$NON-NLS-1$ //$NON-NLS-2$ - } - if (name.length() > 1) { - name = name.replaceAll("_+$", ""); //$NON-NLS-1$ //$NON-NLS-2$ - } - return name; - } - - //----- - - /** - * Creates the AddOnTarget. Invoked by {@link #getAndroidTarget()}. - */ - @Override - @Nullable - protected IAndroidTarget createAndroidTarget() { - LocalSdk sdk = getLocalSdk(); - IFileOp fileOp = sdk.getFileOp(); - - // Parse the addon properties to ensure we can load it. - Pair, String> infos = parseAddonProperties(); - - Map propertyMap = infos.getFirst(); - String error = infos.getSecond(); - - if (error != null) { - appendLoadError("Ignoring add-on '%1$s': %2$s", getLocalDir().getName(), error); - return null; - } - - // Since error==null we're not supposed to encounter any issues loading this add-on. - try { - assert propertyMap != null; - - String api = propertyMap.get(AddonManifestIniProps.ADDON_API); - String name = propertyMap.get(AddonManifestIniProps.ADDON_NAME); - String vendor = propertyMap.get(AddonManifestIniProps.ADDON_VENDOR); - - assert api != null; - assert name != null; - assert vendor != null; - - PlatformTarget baseTarget = null; - - // Look for a platform that has a matching api level or codename. - LocalPkgInfo plat = sdk.getPkgInfo(PkgType.PKG_PLATFORM, - getDesc().getAndroidVersion()); - if (plat instanceof LocalPlatformPkgInfo) { - baseTarget = (PlatformTarget) ((LocalPlatformPkgInfo) plat).getAndroidTarget(); - } - assert baseTarget != null; - - // get the optional description - String description = propertyMap.get(AddonManifestIniProps.ADDON_DESCRIPTION); - - // get the add-on revision - int revisionValue = 1; - String revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION); - if (revision == null) { - revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION_OLD); - } - if (revision != null) { - revisionValue = Integer.parseInt(revision); - } - - // get the optional libraries - String librariesValue = propertyMap.get(AddonManifestIniProps.ADDON_LIBRARIES); - Map libMap = null; - - if (librariesValue != null) { - librariesValue = librariesValue.trim(); - if (!librariesValue.isEmpty()) { - // split in the string into the libraries name - String[] libraries = librariesValue.split(";"); //$NON-NLS-1$ - if (libraries.length > 0) { - libMap = new HashMap(); - for (String libName : libraries) { - libName = libName.trim(); - - // get the library data from the properties - String libData = propertyMap.get(libName); - - if (libData != null) { - // split the jar file from the description - Matcher m = PATTERN_LIB_DATA.matcher(libData); - if (m.matches()) { - libMap.put(libName, new String[] { - m.group(1), m.group(2) }); - } else { - appendLoadError( - "Ignoring library '%1$s', property value has wrong format\n\t%2$s", - libName, libData); - } - } else { - appendLoadError( - "Ignoring library '%1$s', missing property value", - libName, libData); - } - } - } - } - } - - // get the abi list. - ISystemImage[] systemImages = getAddonSystemImages(fileOp); - - // check whether the add-on provides its own rendering info/library. - boolean hasRenderingLibrary = false; - boolean hasRenderingResources = false; - - File dataFolder = new File(getLocalDir(), SdkConstants.FD_DATA); - if (fileOp.isDirectory(dataFolder)) { - hasRenderingLibrary = - fileOp.isFile(new File(dataFolder, SdkConstants.FN_LAYOUTLIB_JAR)); - hasRenderingResources = - fileOp.isDirectory(new File(dataFolder, SdkConstants.FD_RES)) && - fileOp.isDirectory(new File(dataFolder, SdkConstants.FD_FONTS)); - } - - AddOnTarget target = new AddOnTarget( - getLocalDir().getAbsolutePath(), - name, - vendor, - revisionValue, - description, - systemImages, - libMap, - hasRenderingLibrary, - hasRenderingResources, - baseTarget); - - // parse the legacy skins, located under SDK/addons/addon-name/skins/[skin-name] - // and merge with the system-image skins, if any, merging them by name. - File targetSkinFolder = target.getFile(IAndroidTarget.SKINS); - - Map skinsMap = new TreeMap(); - - for (File f : PackageParserUtils.parseSkinFolder(targetSkinFolder, fileOp)) { - skinsMap.put(f.getName().toLowerCase(Locale.US), f); - } - for (ISystemImage si : systemImages) { - for (File f : si.getSkins()) { - skinsMap.put(f.getName().toLowerCase(Locale.US), f); - } - } - - List skins = new ArrayList(skinsMap.values()); - Collections.sort(skins); - - // get the default skin - File defaultSkin = null; - String defaultSkinName = propertyMap.get(AddonManifestIniProps.ADDON_DEFAULT_SKIN); - if (defaultSkinName != null) { - defaultSkin = new File(targetSkinFolder, defaultSkinName); - } else { - // No default skin name specified, use the first one from the addon - // or the default from the platform. - if (skins.size() == 1) { - defaultSkin = skins.get(0); - } else { - defaultSkin = baseTarget.getDefaultSkin(); - } - } - - // get the USB ID (if available) - int usbVendorId = convertId(propertyMap.get(AddonManifestIniProps.ADDON_USB_VENDOR)); - if (usbVendorId != IAndroidTarget.NO_USB_ID) { - target.setUsbVendorId(usbVendorId); - } - - target.setSkins(skins.toArray(new File[skins.size()]), defaultSkin); - - return target; - - } catch (Exception e) { - appendLoadError("Ignoring add-on '%1$s': error %2$s.", - getLocalDir().getName(), e.toString()); - } - - return null; - - } - - /** - * Parses the add-on properties and decodes any error that occurs when loading an addon. - * - * @return A pair with the property map and an error string. Both can be null but not at the - * same time. If a non-null error is present then the property map must be ignored. The error - * should be translatable as it might show up in the SdkManager UI. - */ - @NonNull - private Pair, String> parseAddonProperties() { - Map propertyMap = null; - String error = null; - - IFileOp fileOp = getLocalSdk().getFileOp(); - File addOnManifest = new File(getLocalDir(), SdkConstants.FN_MANIFEST_INI); - - do { - if (!fileOp.isFile(addOnManifest)) { - error = String.format("File not found: %1$s", SdkConstants.FN_MANIFEST_INI); - break; - } - - try { - propertyMap = ProjectProperties.parsePropertyStream( - fileOp.newFileInputStream(addOnManifest), - addOnManifest.getPath(), - null /*log*/); - if (propertyMap == null) { - error = String.format("Failed to parse properties from %1$s", - SdkConstants.FN_MANIFEST_INI); - break; - } - } catch (FileNotFoundException e) { - // this can happen if the system fails to open the file because of too many - // open files. - error = String.format("Failed to parse properties from %1$s: %2$s", - SdkConstants.FN_MANIFEST_INI, e.getMessage()); - break; - } - - // look for some specific values in the map. - // we require name, vendor, and api - String name = propertyMap.get(AddonManifestIniProps.ADDON_NAME); - if (name == null) { - error = addonManifestWarning(AddonManifestIniProps.ADDON_NAME); - break; - } - - String vendor = propertyMap.get(AddonManifestIniProps.ADDON_VENDOR); - if (vendor == null) { - error = addonManifestWarning(AddonManifestIniProps.ADDON_VENDOR); - break; - } - - String api = propertyMap.get(AddonManifestIniProps.ADDON_API); - if (api == null) { - error = addonManifestWarning(AddonManifestIniProps.ADDON_API); - break; - } - - // Look for a platform that has a matching api level or codename. - IAndroidTarget baseTarget = null; - LocalPkgInfo plat = getLocalSdk().getPkgInfo(PkgType.PKG_PLATFORM, - getDesc().getAndroidVersion()); - if (plat instanceof LocalPlatformPkgInfo) { - baseTarget = ((LocalPlatformPkgInfo) plat).getAndroidTarget(); - } - - if (baseTarget == null) { - error = String.format("Unable to find base platform with API level '%1$s'", api); - break; - } - - // get the add-on revision - String revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION); - if (revision == null) { - revision = propertyMap.get(AddonManifestIniProps.ADDON_REVISION_OLD); - } - if (revision != null) { - try { - Integer.parseInt(revision); - } catch (NumberFormatException e) { - // looks like revision does not parse to a number. - error = String.format("%1$s is not a valid number in %2$s.", - AddonManifestIniProps.ADDON_REVISION, SdkConstants.FN_BUILD_PROP); - break; - } - } - - } while(false); - - return Pair.of(propertyMap, error); - } - - /** - * Prepares a warning about the addon being ignored due to a missing manifest value. - * This string will show up in the SdkManager UI. - * - * @param valueName The missing manifest value, for display. - */ - @NonNull - private static String addonManifestWarning(@NonNull String valueName) { - return String.format("'%1$s' is missing from %2$s.", - valueName, SdkConstants.FN_MANIFEST_INI); - } - - /** - * Converts a string representation of an hexadecimal ID into an int. - * @param value the string to convert. - * @return the int value, or {@link IAndroidTarget#NO_USB_ID} if the conversion failed. - */ - private int convertId(@Nullable String value) { - if (value != null && !value.isEmpty()) { - if (PATTERN_USB_IDS.matcher(value).matches()) { - String v = value.substring(2); - try { - return Integer.parseInt(v, 16); - } catch (NumberFormatException e) { - // this shouldn't happen since we check the pattern above, but this is safer. - // the method will return 0 below. - } - } - } - - return IAndroidTarget.NO_USB_ID; - } - - /** - * Get all the system images supported by an add-on target. - * For an add-on, we first look in the new sdk/system-images folders then we look - * for sub-folders in the addon/images directory. - * If none are found but the directory exists and is not empty, assume it's a legacy - * arm eabi system image. - * If any given API appears twice or more, the first occurrence wins. - *

- * Note that it's OK for an add-on to have no system-images at all, since it can always - * rely on the ones from its base platform. - * - * @param fileOp File operation wrapper. - * @return an array of ISystemImage containing all the system images for the target. - * The list can be empty but not null. - */ - @NonNull - private ISystemImage[] getAddonSystemImages(IFileOp fileOp) { - Set found = new TreeSet(); - SetMultimap tagToAbiFound = TreeMultimap.create(); - - - // Look in the system images folders: - // - SDK/system-image/platform/addon-id-tag/abi - // - SDK/system-image/addon-id-tag/abi (many abi possible) - // Optional: look for skins under - // - SDK/system-image/platform/addon-id-tag/abi/skins/skin-name - // - SDK/system-image/addon-id-tag/abi/skins/skin-name - // If we find multiple occurrences of the same platform/abi, the first one read wins. - - LocalPkgInfo[] sysImgInfos = getLocalSdk().getPkgsInfos(PkgType.PKG_ADDON_SYS_IMAGE); - for (LocalPkgInfo pkg : sysImgInfos) { - IPkgDesc d = pkg.getDesc(); - if (pkg instanceof LocalAddonSysImgPkgInfo && - d.hasVendor() && - mAddonDesc.getVendor().equals(d.getVendor()) && - mAddonDesc.getName().equals(d.getTag()) && - Objects.equal(mAddonDesc.getAndroidVersion(), pkg.getDesc().getAndroidVersion())) { - final IdDisplay tag = mAddonDesc.getName(); - final String abi = d.getPath(); - if (abi != null && !tagToAbiFound.containsEntry(tag, abi)) { - found.add(((LocalAddonSysImgPkgInfo)pkg).getSystemImage()); - tagToAbiFound.put(tag, abi); - } - } - } - - // Look for sub-directories: - // - SDK/addons/addon-name/images/abi (multiple abi possible) - // - SDK/addons/addon-name/armeabi (legacy support) - boolean useLegacy = true; - boolean hasImgFiles = false; - final IdDisplay defaultTag = SystemImage.DEFAULT_TAG; - - File imagesDir = new File(getLocalDir(), SdkConstants.OS_IMAGES_FOLDER); - File[] files = fileOp.listFiles(imagesDir); - for (File file : files) { - if (fileOp.isDirectory(file)) { - useLegacy = false; - String abi = file.getName(); - if (!tagToAbiFound.containsEntry(defaultTag, abi)) { - found.add(new SystemImage( - file, - LocationType.IN_IMAGES_SUBFOLDER, - SystemImage.DEFAULT_TAG, - mAddonDesc.getVendor(), - abi, - LegacyFileOp.EMPTY_FILE_ARRAY)); - tagToAbiFound.put(defaultTag, abi); - } - } else if (!hasImgFiles && fileOp.isFile(file)) { - if (file.getName().endsWith(".img")) { //$NON-NLS-1$ - // The legacy images folder is only valid if it contains some .img files - hasImgFiles = true; - } - } - } - - if (useLegacy && - hasImgFiles && - fileOp.isDirectory(imagesDir) && - !tagToAbiFound.containsEntry(defaultTag, SdkConstants.ABI_ARMEABI)) { - // We found no sub-folder system images but it looks like the top directory - // has some img files in it. It must be a legacy ARM EABI system image folder. - found.add(new SystemImage( - imagesDir, - LocationType.IN_LEGACY_FOLDER, - SystemImage.DEFAULT_TAG, - SdkConstants.ABI_ARMEABI, - LegacyFileOp.EMPTY_FILE_ARRAY)); - } - - return found.toArray(new ISystemImage[found.size()]); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonSysImgPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonSysImgPkgInfo.java deleted file mode 100644 index e02c8e95..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalAddonSysImgPkgInfo.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2014 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Local add-on system-image package, for a given addon's {@link AndroidVersion} and given ABI. - * The system-image tag is the add-on name. - * The package itself has a major revision. - * There should be only one for a given android platform version & ABI. - */ -public class LocalAddonSysImgPkgInfo extends LocalPkgInfo { - - - @NonNull - private final IPkgDesc mDesc; - - public LocalAddonSysImgPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @Nullable IdDisplay addonVendor, - @Nullable IdDisplay addonName, - @NonNull String abi, - @NonNull MajorRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newAddonSysImg(version, addonVendor, addonName, abi, revision) - .create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } - - public ISystemImage getSystemImage() { - return LocalSysImgPkgInfo.getSystemImage(mDesc, getLocalDir(), getLocalSdk().getFileOp()); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalBuildToolPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalBuildToolPkgInfo.java deleted file mode 100644 index 0251cc3c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalBuildToolPkgInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -public class LocalBuildToolPkgInfo extends LocalPkgInfo { - - - @Nullable - private final BuildToolInfo mBuildToolInfo; - @NonNull - private final IPkgDesc mDesc; - - public LocalBuildToolPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull FullRevision revision, - @Nullable BuildToolInfo btInfo) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newBuildTool(revision).create(); - mBuildToolInfo = btInfo; - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } - - @Nullable - public BuildToolInfo getBuildToolInfo() { - return mBuildToolInfo; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDirInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDirInfo.java deleted file mode 100644 index 4414fc6c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDirInfo.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2014 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; - -import java.io.File; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Map; -import java.util.zip.Adler32; - -/** - * Keeps information on a visited directory to quickly determine if it - * has changed later. A directory has changed if its timestamp has been - * modified, or if an underlying source.properties file has changed in - * timestamp or checksum. - *

- * Note that depending on the filesystem & OS, the content of the files in - * a directory can change without the directory's last-modified property - * changing. To have a consistent behavior between OSes, we compute a quick - * checksum using all the files & directories modified timestamps. - * The content of files is not included though, except for the checksum on - * the source.property file since this one is the most important for the SDK. - *

- * The {@link #hashCode()} and {@link #equals(Object)} methods directly - * defer to the underlying File object. This allows the DirInfo to be placed - * into a map and still call {@link Map#containsKey(Object)} with a File - * object to check whether there's a corresponding DirInfo in the map. - */ -class LocalDirInfo { - @NonNull - private final IFileOp mFileOp; - @NonNull - private final File mDir; - private final long mDirModifiedTS; - private final long mDirChecksum; - private final long mPropsModifiedTS; - private final long mPropsChecksum; - - /** - * Creates a new immutable {@link LocalDirInfo}. - * - * @param LegacyFileOp The {@link LegacyFileOp} to use for all file-based interactions. - * @param dir The platform/addon directory of the target. It should be a directory. - */ - public LocalDirInfo(@NonNull IFileOp LegacyFileOp, @NonNull File dir) { - mFileOp = LegacyFileOp; - mDir = dir; - mDirModifiedTS = mFileOp.lastModified(dir); - - // Capture some info about the source.properties file if it exists. - // We use propsModifiedTS == 0 to mean there is no props file. - long propsChecksum = 0; - long propsModifiedTS = 0; - File props = new File(dir, SdkConstants.FN_SOURCE_PROP); - if (mFileOp.isFile(props)) { - propsModifiedTS = mFileOp.lastModified(props); - propsChecksum = getFileChecksum(props); - } - mPropsModifiedTS = propsModifiedTS; - mPropsChecksum = propsChecksum; - mDirChecksum = getDirChecksum(mDir); - } - - /** - * Checks whether the directory/source.properties attributes have changed. - * - * @return True if the directory modified timestamp or - * its source.property files have changed. - */ - public boolean hasChanged() { - // Does platform directory still exist? - if (!mFileOp.isDirectory(mDir)) { - return true; - } - // Has platform directory modified-timestamp changed? - if (mDirModifiedTS != mFileOp.lastModified(mDir)) { - return true; - } - - File props = new File(mDir, SdkConstants.FN_SOURCE_PROP); - - // The directory did not have a props file if target was null or - // if mPropsModifiedTS is 0. - boolean hadProps = mPropsModifiedTS != 0; - - // Was there a props file and it vanished, or there wasn't and there's one now? - if (hadProps != mFileOp.isFile(props)) { - return true; - } - - if (hadProps) { - // Has source.props file modified-timestamp changed? - if (mPropsModifiedTS != mFileOp.lastModified(props)) { - return true; - } - // Had the content of source.props changed? - if (mPropsChecksum != getFileChecksum(props)) { - return true; - } - } - - // Has the deep directory checksum changed? - if (mDirChecksum != getDirChecksum(mDir)) { - return true; - } - - return false; - } - - /** - * Computes an adler32 checksum (source.props are small files, so this - * should be OK with an acceptable collision rate.) - */ - private long getFileChecksum(@NonNull File file) { - InputStream fis = null; - try { - fis = mFileOp.newFileInputStream(file); - Adler32 a = new Adler32(); - byte[] buf = new byte[1024]; - int n; - while ((n = fis.read(buf)) > 0) { - a.update(buf, 0, n); - } - return a.getValue(); - } catch (Exception ignore) { - } finally { - try { - if (fis != null) { - fis.close(); - } - } catch(Exception ignore) {} - } - return 0; - } - - /** - * Computes a checksum using the last-modified attributes of all - * the files and first-leveldirectories in this root directory. - *

- * Heuristic: the SDK Manager updates package by replacing whole directories - * so we don't need to do a recursive deep-first checksum of all files. Only - * the top-level of the package directory should be sufficient to detect - * SDK updates. - */ - private long getDirChecksum(@NonNull File dir) { - long checksum = mFileOp.lastModified(dir); - - // Get the file & directory list sorted by case-insensitive name - // to make the checksum more consistent. - File[] files = mFileOp.listFiles(dir); - Arrays.sort(files, new Comparator() { - @Override - public int compare(File o1, File o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }); - for (File file : files) { - checksum = 31 * checksum | mFileOp.lastModified(file); - } - return checksum; - } - - /** Returns a visual representation of this object for debugging. */ - @Override - public String toString() { - String s = String.format(""; //$NON-NLS-1$ - } - - /** - * Returns the hashCode of the underlying File object. - *

- * When a {@link LocalDirInfo} is placed in a map, what matters is to use the underlying - * File object as the key so {@link #hashCode()} and {@link #equals(Object)} both - * return the properties of the underlying File object. - * - * @see File#hashCode() - */ - @Override - public int hashCode() { - return mDir.hashCode(); - } - - /** - * Checks equality of the underlying File object. - *

- * When a {@link LocalDirInfo} is placed in a map, what matters is to use the underlying - * File object as the key so {@link #hashCode()} and {@link #equals(Object)} both - * return the properties of the underlying File object. - * - * @see File#equals(Object) - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof File) { - return mDir.equals(obj); - } else if (obj instanceof LocalDirInfo) { - return mDir.equals(((LocalDirInfo) obj).mDir); - } else if (obj instanceof MapComparator) { - return mDir.equals(((MapComparator) obj).mDir); - } - return false; - } - - /** - * Helper for Map.contains() to make sure we're comparing the inner directory File - * object and not the outer wrapper itself. - */ - public static class MapComparator { - private final File mDir; - - public MapComparator(File dir) { - mDir = dir; - } - - /** - * Returns the hashCode of the underlying File object. - *

- * When a {@link LocalDirInfo} is placed in a map, what matters is to use the underlying - * File object as the key so {@link #hashCode()} and {@link #equals(Object)} both - * return the properties of the underlying File object. - * - * @see File#hashCode() - */ - @Override - public int hashCode() { - return mDir.hashCode(); - } - - /** - * Checks equality of the underlying File object. - *

- * When a {@link LocalDirInfo} is placed in a map, what matters is to use the underlying - * File object as the key so {@link #hashCode()} and {@link #equals(Object)} both - * return the properties of the underlying File object. - * - * @see File#equals(Object) - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof File) { - return mDir.equals(obj); - } else if (obj instanceof LocalDirInfo) { - return mDir.equals(((LocalDirInfo) obj).mDir); - } else if (obj instanceof MapComparator) { - return mDir.equals(((MapComparator) obj).mDir); - } - return false; - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDocPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDocPkgInfo.java deleted file mode 100644 index 004f4503..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalDocPkgInfo.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -public class LocalDocPkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDesc mDesc; - - public LocalDocPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @NonNull MajorRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newDoc(version, revision).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalExtraPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalExtraPkgInfo.java deleted file mode 100644 index 5ec811bd..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalExtraPkgInfo.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IPkgDescExtra; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -public class LocalExtraPkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDescExtra mDesc; - - public LocalExtraPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull IdDisplay vendor, - @NonNull String path, - @Nullable String displayName, - @NonNull String[] oldPaths, - @NonNull NoPreviewRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = (IPkgDescExtra) PkgDesc.Builder.newExtra( - vendor, - path, - displayName, - oldPaths, - revision).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } - - @NonNull - public String[] getOldPaths() { - return mDesc.getOldPaths(); - } - - // --- helpers --- - - /** - * Used to produce a suitable name-display based on the extra's path - * and vendor display string in addon-3 schemas. - * - * @param vendor The vendor id of the extra. - * @param extraPath The non-null path of the extra. - * @return A non-null display name based on the extra's path id. - */ - public static String getPrettyName(@Nullable IdDisplay vendor, @NonNull String extraPath) { - String name = extraPath; - - // In the past, we used to save the extras in a folder vendor-path, - // and that "vendor" would end up in the path when we reload the extra from - // disk. Detect this and compensate. - String disp = vendor == null ? null : vendor.getDisplay(); - if (disp != null && !disp.isEmpty()) { - if (name.startsWith(disp + "-")) { //$NON-NLS-1$ - name = name.substring(disp.length() + 1); - } - } - - // Uniformize all spaces in the name - if (name != null) { - name = name.replaceAll("[ _\t\f-]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$ - } - if (name == null || name.isEmpty()) { - name = "Unknown Extra"; - } - - if (disp != null && !disp.isEmpty()) { - name = disp + " " + name; //$NON-NLS-1$ - name = name.replaceAll("[ _\t\f-]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Look at all lower case characters in range [1..n-1] and replace them by an upper - // case if they are preceded by a space. Also upper cases the first character of the - // string. - boolean changed = false; - char[] chars = name.toCharArray(); - for (int n = chars.length - 1, i = 0; i < n; i++) { - if (Character.isLowerCase(chars[i]) && (i == 0 || chars[i - 1] == ' ')) { - chars[i] = Character.toUpperCase(chars[i]); - changed = true; - } - } - if (changed) { - name = new String(chars); - } - - // Special case: reformat a few typical acronyms. - name = name.replaceAll(" Usb ", " USB "); //$NON-NLS-1$ - name = name.replaceAll(" Api ", " API "); //$NON-NLS-1$ - - return name; - } -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalNdkPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalNdkPkgInfo.java deleted file mode 100644 index 88583005..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalNdkPkgInfo.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Local package representing the Android NDK - */ -public class LocalNdkPkgInfo extends LocalPkgInfo { - @NonNull - private final IPkgDesc mDesc; - - protected LocalNdkPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull FullRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newNdk(revision).setDescriptionShort("Android NDK").setListDisplay("Android NDK").create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPkgInfo.java deleted file mode 100644 index 4f8982e7..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPkgInfo.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.repository.IDescription; -import com.android.sdklib.repository.IListDescription; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.descriptors.IPkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Information about a locally installed package. - *

- * Local package information is retrieved via the {@link LocalSdk} object. - * Clients should not need to create instances of {@link LocalPkgInfo} directly. - * Instead please use the {@link LocalSdk} methods to parse and retrieve packages. - *

- */ -public abstract class LocalPkgInfo - implements IDescription, IListDescription, Comparable { - - private final LocalSdk mLocalSdk; - private final File mLocalDir; - private final Properties mSourceProperties; - - private String mLoadError; - - protected LocalPkgInfo(@NonNull LocalSdk localSdk, @NonNull File localDir, @NonNull Properties sourceProps) { - mLocalSdk = localSdk; - mLocalDir = localDir; - mSourceProperties = sourceProps; - } - - //---- Attributes ---- - - @NonNull - public LocalSdk getLocalSdk() { - return mLocalSdk; - } - - @NonNull - public File getLocalDir() { - return mLocalDir; - } - - @NonNull - public Properties getSourceProperties() { - return mSourceProperties; - } - - @Nullable - public String getLoadError() { - return mLoadError; - } - - // ---- - - /** - * Returns the {@link IPkgDesc} describing this package. - */ - @NonNull - public abstract IPkgDesc getDesc(); - - - //---- Ordering ---- - - /** - * Comparison is solely done based on the {@link IPkgDesc}. - *

- * Other local attributes (local directory, source properties) - * are not used in the comparison. Consequently {@link #compareTo(LocalPkgInfo)} - * does not match {@link #equals(Object)} and the {@link #hashCode()} properties. - */ - @Override - public int compareTo(@NonNull LocalPkgInfo o) { - return getDesc().compareTo(o.getDesc()); - } - - /** - * String representation for debugging purposes. - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append('<').append(this.getClass().getSimpleName()).append(' '); - builder.append(getDesc().toString()); - builder.append('>'); - return builder.toString(); - } - - /** - * Computes a hash code specific to this instance based on the underlying - * {@link IPkgDesc} but also specific local properties such a local directory, - * and actual source properties. - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((getDesc() == null) ? 0 : getDesc().hashCode()); - result = prime * result + ((mLocalDir == null) ? 0 : mLocalDir.hashCode()); - result = prime * result + ((mSourceProperties == null) ? 0 : mSourceProperties.hashCode()); - return result; - } - - /** - * Computes object equality to this instance based on the underlying - * {@link IPkgDesc} but also specific local properties such a local directory, - * update available and actual source properties. This is different from - * the behavior of {@link #compareTo(LocalPkgInfo)} which only uses the - * {@link IPkgDesc} for ordering. - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof LocalPkgInfo)) { - return false; - } - LocalPkgInfo other = (LocalPkgInfo)obj; - - if (!getDesc().equals(other.getDesc())) { - return false; - } - if (mLocalDir == null) { - if (other.mLocalDir != null) { - return false; - } - } - else if (!mLocalDir.equals(other.mLocalDir)) { - return false; - } - if (mSourceProperties == null) { - if (other.mSourceProperties != null) { - return false; - } - } - else if (!mSourceProperties.equals(other.mSourceProperties)) { - return false; - } - return true; - } - - - //---- Package Management ---- - - /** - * A "broken" package is installed but is not fully operational. - *

- * For example an addon that lacks its underlying platform or a tool package - * that lacks some of its binaries or essentially files. - *

- * Operational code should generally ignore broken packages. - * Only the SDK Updater cares about displaying them so that they can be fixed. - */ - public boolean hasLoadError() { - return mLoadError != null; - } - - void appendLoadError(@NonNull String format, Object... params) { - String loadError = String.format(format, params); - if (mLoadError == null) { - mLoadError = loadError; - } - else { - mLoadError = mLoadError + '\n' + loadError; - } - } - - @NonNull - @Override - public String getListDescription() { - return getDesc().getListDescription(); - } - - @Override - public String getShortDescription() { - // TODO revisit to differentiate from list-description depending - // on how we'll use it in the sdkman UI. - return getListDescription(); - } - - @Override - public String getLongDescription() { - StringBuilder sb = new StringBuilder(); - IPkgDesc desc = getDesc(); - - sb.append(desc.getListDescription()).append('\n'); - - if (desc.hasVendor()) { - assert desc.getVendor() != null; - sb.append("By ").append(desc.getVendor().getDisplay()).append('\n'); - } - - if (desc.hasMinPlatformToolsRev()) { - assert desc.getMinPlatformToolsRev() != null; - sb.append("Requires Platform-Tools revision ").append(desc.getMinPlatformToolsRev().toShortString()).append('\n'); - } - - if (desc.hasMinToolsRev()) { - assert desc.getMinToolsRev() != null; - sb.append("Requires Tools revision ").append(desc.getMinToolsRev().toShortString()).append('\n'); - } - - sb.append("Location: ").append(mLocalDir.getAbsolutePath()); - - return sb.toString(); - } - - /** - * Deletes the files in the SDK corresponding to this package. - */ - public void delete() { - new LegacyFileOp().deleteFileOrFolder(getLocalDir()); - } - -} - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformPkgInfo.java deleted file mode 100644 index 1ccb2be7..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformPkgInfo.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.IAndroidTarget.OptionalLibrary; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.ISystemImage.LocationType; -import com.android.sdklib.SdkManager.LayoutlibVersion; -import com.android.sdklib.SystemImage; -import com.android.sdklib.internal.androidTarget.OptionalLibraryImpl; -import com.android.sdklib.internal.androidTarget.PlatformTarget; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.android.sdklib.repository.descriptors.PkgType; -import com.google.common.base.Charsets; -import com.google.common.collect.Lists; -import com.google.common.collect.SetMultimap; -import com.google.common.collect.TreeMultimap; -import com.google.common.io.Files; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.io.File; -import java.io.FileNotFoundException; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeSet; - -@SuppressWarnings("ConstantConditions") -public class LocalPlatformPkgInfo extends LocalPkgInfo { - - public static final String PROP_VERSION_SDK = "ro.build.version.sdk"; //$NON-NLS-1$ - public static final String PROP_VERSION_CODENAME = "ro.build.version.codename"; //$NON-NLS-1$ - public static final String PROP_VERSION_RELEASE = "ro.build.version.release"; //$NON-NLS-1$ - - @NonNull - private final IPkgDesc mDesc; - - /** Android target, lazyly loaded from #getAndroidTarget */ - private IAndroidTarget mTarget; - private boolean mLoaded; - - public LocalPlatformPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull FullRevision minToolsRev) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newPlatform(version, revision, minToolsRev).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } - - /** The "path" of a Platform is its Target Hash. */ - @NonNull - public String getTargetHash() { - return getDesc().getPath(); - } - - @Nullable - public IAndroidTarget getAndroidTarget() { - if (!mLoaded) { - mTarget = createAndroidTarget(); - mLoaded = true; - } - return mTarget; - } - - public boolean isLoaded() { - return mLoaded; - } - - //----- - - /** - * Creates the PlatformTarget. Invoked by {@link #getAndroidTarget()}. - */ - @SuppressWarnings("ConstantConditions") - @Nullable - protected IAndroidTarget createAndroidTarget() { - LocalSdk sdk = getLocalSdk(); - IFileOp fileOp = sdk.getFileOp(); - File platformFolder = getLocalDir(); - File buildProp = new File(platformFolder, SdkConstants.FN_BUILD_PROP); - File sourcePropFile = new File(platformFolder, SdkConstants.FN_SOURCE_PROP); - - if (!fileOp.isFile(buildProp) || !fileOp.isFile(sourcePropFile)) { - appendLoadError("Ignoring platform '%1$s': %2$s is missing.", //$NON-NLS-1$ - platformFolder.getName(), - SdkConstants.FN_BUILD_PROP); - return null; - } - - Map platformProp = new HashMap(); - - // add all the property files - Map map = null; - - try { - map = ProjectProperties.parsePropertyStream( - fileOp.newFileInputStream(buildProp), - buildProp.getPath(), - null /*log*/); - if (map != null) { - platformProp.putAll(map); - } - } catch (FileNotFoundException ignore) {} - - try { - map = ProjectProperties.parsePropertyStream( - fileOp.newFileInputStream(sourcePropFile), - sourcePropFile.getPath(), - null /*log*/); - if (map != null) { - platformProp.putAll(map); - } - } catch (FileNotFoundException ignore) {} - - File sdkPropFile = new File(platformFolder, SdkConstants.FN_SDK_PROP); - if (fileOp.isFile(sdkPropFile)) { // obsolete platforms don't have this. - try { - map = ProjectProperties.parsePropertyStream( - fileOp.newFileInputStream(sdkPropFile), - sdkPropFile.getPath(), - null /*log*/); - if (map != null) { - platformProp.putAll(map); - } - } catch (FileNotFoundException ignore) {} - } - - // look for some specific values in the map. - - // api level - int apiNumber; - String stringValue = platformProp.get(PROP_VERSION_SDK); - if (stringValue == null) { - appendLoadError("Ignoring platform '%1$s': %2$s is missing from '%3$s'", - platformFolder.getName(), PROP_VERSION_SDK, - SdkConstants.FN_BUILD_PROP); - return null; - } else { - try { - apiNumber = Integer.parseInt(stringValue); - } catch (NumberFormatException e) { - // looks like apiNumber does not parse to a number. - // Ignore this platform. - appendLoadError( - "Ignoring platform '%1$s': %2$s is not a valid number in %3$s.", - platformFolder.getName(), PROP_VERSION_SDK, - SdkConstants.FN_BUILD_PROP); - return null; - } - } - - // Codename must be either null or a platform codename. - // REL means it's a release version and therefore the codename should be null. - AndroidVersion apiVersion = - new AndroidVersion(apiNumber, platformProp.get(PROP_VERSION_CODENAME)); - - // version string - String apiName = platformProp.get(PkgProps.PLATFORM_VERSION); - if (apiName == null) { - apiName = platformProp.get(PROP_VERSION_RELEASE); - } - if (apiName == null) { - appendLoadError( - "Ignoring platform '%1$s': %2$s is missing from '%3$s'", - platformFolder.getName(), PROP_VERSION_RELEASE, - SdkConstants.FN_BUILD_PROP); - return null; - } - - // platform rev number & layoutlib version are extracted from the source.properties - // saved by the SDK Manager when installing the package. - - int revision = 1; - LayoutlibVersion layoutlibVersion = null; - try { - revision = Integer.parseInt(platformProp.get(PkgProps.PKG_REVISION)); - } catch (NumberFormatException e) { - // do nothing, we'll keep the default value of 1. - } - - try { - String propApi = platformProp.get(PkgProps.LAYOUTLIB_API); - String propRev = platformProp.get(PkgProps.LAYOUTLIB_REV); - int llApi = propApi == null ? LayoutlibVersion.NOT_SPECIFIED : - Integer.parseInt(propApi); - int llRev = propRev == null ? LayoutlibVersion.NOT_SPECIFIED : - Integer.parseInt(propRev); - if (llApi > LayoutlibVersion.NOT_SPECIFIED && - llRev >= LayoutlibVersion.NOT_SPECIFIED) { - layoutlibVersion = new LayoutlibVersion(llApi, llRev); - } - } catch (NumberFormatException e) { - // do nothing, we'll ignore the layoutlib version if it's invalid - } - - // api number and name look valid, perform a few more checks - String err = checkPlatformContent(fileOp, platformFolder); - if (err != null) { - appendLoadError("%s", err); //$NLN-NLS-1$ - return null; - } - - ISystemImage[] systemImages = getPlatformSystemImages(fileOp, platformFolder, apiVersion); - - // create the target. - PlatformTarget pt = new PlatformTarget( - sdk.getLocation().getPath(), - platformFolder.getAbsolutePath(), - apiVersion, - apiName, - revision, - layoutlibVersion, - systemImages, - platformProp, - getOptionalLibraries(platformFolder), - sdk.getLatestBuildTool()); - - // add the skins from the platform. Make a copy to not modify the original collection. - List skins = new ArrayList(PackageParserUtils.parseSkinFolder(pt.getFile(IAndroidTarget.SKINS), fileOp)); - - // add the system-image specific skins, if any. - for (ISystemImage systemImage : systemImages) { - skins.addAll(Arrays.asList(systemImage.getSkins())); - } - - pt.setSkins(skins.toArray(new File[skins.size()])); - - // add path to the non-legacy samples package if it exists - LocalPkgInfo samples = sdk.getPkgInfo(PkgType.PKG_SAMPLE, getDesc().getAndroidVersion()); - if (samples != null) { - pt.setSamplesPath(samples.getLocalDir().getAbsolutePath()); - } - - // add path to the non-legacy sources package if it exists - LocalPkgInfo sources = sdk.getPkgInfo(PkgType.PKG_SOURCE, getDesc().getAndroidVersion()); - if (sources != null) { - pt.setSourcesPath(sources.getLocalDir().getAbsolutePath()); - } - - return pt; - } - - /** - * Get all the system images supported by a platform target. - * For a platform, we first look in the new sdk/system-images folders then we - * look for sub-folders in the platform/images directory and/or the one legacy - * folder. - * If any given API appears twice or more, the first occurrence wins. - * - * @param fileOp File operation wrapper. - * @param platformDir Root of the platform target being loaded. - * @param apiVersion API level + codename of platform being loaded. - * @return an array of ISystemImage containing all the system images for the target. - * The list can be empty but not null. - */ - @NonNull - private ISystemImage[] getPlatformSystemImages(IFileOp fileOp, - File platformDir, - AndroidVersion apiVersion) { - Set found = new TreeSet(); - SetMultimap tagToAbiFound = TreeMultimap.create(); - - - // Look in the SDK/system-image/platform-n/tag/abi folders. - // Look in the SDK/system-image/platform-n/abi folders. - // If we find multiple occurrences of the same platform/abi, the first one read wins. - - LocalPkgInfo[] sysImgInfos = getLocalSdk().getPkgsInfos(PkgType.PKG_SYS_IMAGE); - for (LocalPkgInfo pkg : sysImgInfos) { - IPkgDesc d = pkg.getDesc(); - if (pkg instanceof LocalSysImgPkgInfo && - !d.hasVendor() && - apiVersion.equals(d.getAndroidVersion())) { - IdDisplay tag = d.getTag(); - String abi = d.getPath(); - if (tag != null && abi != null && !tagToAbiFound.containsEntry(tag, abi)) { - found.add(((LocalSysImgPkgInfo)pkg).getSystemImage()); - tagToAbiFound.put(tag, abi); - } - } - } - - // Look in either the platform/images/abi or the legacy folder - File imgDir = new File(platformDir, SdkConstants.OS_IMAGES_FOLDER); - File[] files = fileOp.listFiles(imgDir); - boolean useLegacy = true; - boolean hasImgFiles = false; - final IdDisplay defaultTag = SystemImage.DEFAULT_TAG; - - // Look for sub-directories - for (File file : files) { - if (fileOp.isDirectory(file)) { - useLegacy = false; - String abi = file.getName(); - if (!tagToAbiFound.containsEntry(defaultTag, abi)) { - found.add(new SystemImage( - file, - LocationType.IN_IMAGES_SUBFOLDER, - defaultTag, - abi, - LegacyFileOp.EMPTY_FILE_ARRAY)); - tagToAbiFound.put(defaultTag, abi); - } - } else if (!hasImgFiles && fileOp.isFile(file)) { - if (file.getName().endsWith(".img")) { //$NON-NLS-1$ - hasImgFiles = true; - } - } - } - - if (useLegacy && - hasImgFiles && - fileOp.isDirectory(imgDir) && - !tagToAbiFound.containsEntry(defaultTag, SdkConstants.ABI_ARMEABI)) { - // We found no sub-folder system images but it looks like the top directory - // has some img files in it. It must be a legacy ARM EABI system image folder. - found.add(new SystemImage( - imgDir, - LocationType.IN_LEGACY_FOLDER, - defaultTag, - SdkConstants.ABI_ARMEABI, - LegacyFileOp.EMPTY_FILE_ARRAY)); - } - - return found.toArray(new ISystemImage[found.size()]); - } - - private List getOptionalLibraries(@NonNull File platformDir) { - File optionalDir = new File(platformDir, "optional"); - if (!optionalDir.isDirectory()) { - return Collections.emptyList(); - } - - File optionalJson = new File(optionalDir, "optional.json"); - if (!optionalJson.isFile()) { - return Collections.emptyList(); - } - - return getLibsFromJson(optionalJson); - } - - public static class Library { - String name; - String jar; - boolean manifest; - } - - - @VisibleForTesting - static List getLibsFromJson(@NonNull File jsonFile) { - - Gson gson = new Gson(); - - try { - Type collectionType = new TypeToken>() { - }.getType(); - Collection libs = gson - .fromJson(Files.newReader(jsonFile, Charsets.UTF_8), collectionType); - - // convert into the right format. - List optionalLibraries = Lists.newArrayListWithCapacity(libs.size()); - - File rootFolder = jsonFile.getParentFile(); - for (Library lib : libs) { - optionalLibraries.add(new OptionalLibraryImpl( - lib.name, - new File(rootFolder, lib.jar), - lib.name, - lib.manifest)); - } - - return optionalLibraries; - } catch (FileNotFoundException e) { - // shouldn't happen since we've checked the file is here, but can happen in - // some cases (too many files open). - return Collections.emptyList(); - } - } - - /** List of items in the platform to check when parsing it. These paths are relative to the - * platform root folder. */ - private static final String[] sPlatformContentList = new String[] { - SdkConstants.FN_FRAMEWORK_LIBRARY, - SdkConstants.FN_FRAMEWORK_AIDL, - }; - - /** - * Checks the given platform has all the required files, and returns true if they are all - * present. - *

This checks the presence of the following files: android.jar, framework.aidl, aapt(.exe), - * aidl(.exe), dx(.bat), and dx.jar - * - * @param fileOp File operation wrapper. - * @param platform The folder containing the platform. - * @return An error description if platform is rejected; null if no error is detected. - */ - @NonNull - private static String checkPlatformContent(IFileOp fileOp, @NonNull File platform) { - for (String relativePath : sPlatformContentList) { - File f = new File(platform, relativePath); - if (!fileOp.exists(f)) { - return String.format( - "Ignoring platform '%1$s': %2$s is missing.", //$NON-NLS-1$ - platform.getName(), relativePath); - } - } - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformToolPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformToolPkgInfo.java deleted file mode 100644 index 281c64e4..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalPlatformToolPkgInfo.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -public class LocalPlatformToolPkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDesc mDesc; - - public LocalPlatformToolPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull FullRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newPlatformTool(revision).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSamplePkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSamplePkgInfo.java deleted file mode 100644 index d8159d61..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSamplePkgInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Local sample package, for a given platform's {@link AndroidVersion}. - * The package itself has a major revision. - * There should be only one for a given android platform version. - */ -public class LocalSamplePkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDesc mDesc; - - public LocalSamplePkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @NonNull MajorRevision revision, - @NonNull FullRevision minToolsRev) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newSample(version, revision, minToolsRev).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSdk.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSdk.java deleted file mode 100644 index 72597cd3..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSdk.java +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.annotations.concurrency.GuardedBy; -import com.android.sdklib.*; -import com.android.sdklib.AndroidVersion.AndroidVersionException; -import com.android.sdklib.internal.androidTarget.MissingTarget; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDescExtra; -import com.android.sdklib.repository.descriptors.PkgType; -import com.google.common.collect.*; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - -/** - * This class keeps information on the current locally installed SDK. - * It tries to lazily load information as much as possible. - *

- * Packages are accessed by their type and a main query attribute, depending on the - * package type. There are different versions of {@link #getPkgInfo} which depend on the - * query attribute. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
TypeQuery parameterGetter
ToolsUnique instance{@code getPkgInfo(PkgType.PKG_TOOLS)} => {@link LocalPkgInfo}
Platform-ToolsUnique instance{@code getPkgInfo(PkgType.PKG_PLATFORM_TOOLS)} => {@link LocalPkgInfo}
DocsUnique instance{@code getPkgInfo(PkgType.PKG_DOCS)} => {@link LocalPkgInfo}
Build-Tools{@link FullRevision}{@code getLatestBuildTool()} => {@link BuildToolInfo},
- * or {@code getBuildTool(FullRevision)} => {@link BuildToolInfo},
- * or {@code getPkgInfo(PkgType.PKG_BUILD_TOOLS, FullRevision)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_BUILD_TOOLS)} => {@link LocalPkgInfo}[]
ExtrasString vendor/path{@code getExtra(String)} => {@link LocalExtraPkgInfo},
- * or {@code getPkgInfo(PkgType.PKG_EXTRAS, String)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_EXTRAS)} => {@link LocalPkgInfo}[]
Sources{@link AndroidVersion}{@code getPkgInfo(PkgType.PKG_SOURCES, AndroidVersion)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_SOURCES)} => {@link LocalPkgInfo}[]
Samples{@link AndroidVersion}{@code getPkgInfo(PkgType.PKG_SAMPLES, AndroidVersion)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_SAMPLES)} => {@link LocalPkgInfo}[]
Platforms{@link AndroidVersion}{@code getPkgInfo(PkgType.PKG_PLATFORMS, AndroidVersion)} => {@link LocalPkgInfo},
- * or {@code getPkgInfo(PkgType.PKG_ADDONS, String)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_PLATFORMS)} => {@link LocalPkgInfo}[],
- * or {@code getTargetFromHashString(String)} => {@link IAndroidTarget}
Add-ons{@link AndroidVersion} x String vendor/path{@code getPkgInfo(PkgType.PKG_ADDONS, String)} => {@link LocalPkgInfo},
- * or {@code getPkgsInfos(PkgType.PKG_ADDONS)} => {@link LocalPkgInfo}[],
- * or {@code getTargetFromHashString(String)} => {@link IAndroidTarget}
System images{@link AndroidVersion} x {@link String} ABI{@code getPkgsInfos(PkgType.PKG_SYS_IMAGES)} => {@link LocalPkgInfo}[]
- * - * Apps/libraries that use it are encouraged to keep an existing instance around - * (using a singleton or similar mechanism). - *

- * Threading: All accessor methods are synchronized on the same internal lock so - * it's safe to call them from any thread, even concurrently.
- * A method like {@code getPkgsInfos} returns a copy of its data array, which objects are - * not altered after creation, so its value is not influenced by the internal state after - * it returns. - *

- * - * Implementation Background: - *

    - *
  • The sdk manager has a set of "Package" classes that cover both local - * and remote SDK operations. - *
  • Goal was to split it in 2 cleanly separated parts: {@link LocalSdk} parses sdk on disk, - * and a separate class wraps the downloaded manifest (this is now handled within Studio only) - *
  • The local SDK should be a singleton accessible somewhere, so there will be one in ADT - * (via the Sdk instance), one in Studio, and one in the command line tool.
    - * Right now there's a bit of mess with some classes creating a temp LocalSdkParser, - * some others using an SdkManager instance, and that needs to be sorted out. - *
  • As a transition, the SdkManager instance wraps a LocalSdk and uses this. Eventually the - * SdkManager.java class will go away (its name is totally misleading, for starters.) - *
  • The current LocalSdkParser stays as-is for compatibility purposes and the goal is also - * to totally remove it when the SdkManager class goes away. - *
- * @version 2 of the {@code SdkManager} class, essentially. - */ -public class LocalSdk { - - /** Location of the SDK. Maybe null. Can be changed. */ - private File mSdkRoot; - /** File operation object. (Used for overriding in mock testing.) */ - private final IFileOp mFileOp; - /** List of package information loaded so far. Lazily populated. */ - @GuardedBy(value="mLocalPackages") - private final Multimap mLocalPackages = TreeMultimap.create(); - /** Directories already parsed into {@link #mLocalPackages}. */ - @GuardedBy(value="mLocalPackages") - private final Multimap mVisitedDirs = HashMultimap.create(); - /** A legacy build-tool for older platform-tools < 17. */ - private BuildToolInfo mLegacyBuildTools; - /** Cache of targets from local sdk. See {@link #getTargets()}. */ - @GuardedBy(value="mLocalPackages") - private List mCachedTargets = null; - private Set mCachedMissingTargets = null; - - /** - * Creates an initial LocalSdk instance with an unknown location. - */ - public LocalSdk() { - mFileOp = new LegacyFileOp(); - } - - /** - * Creates an initial LocalSdk instance for a known SDK location. - * - * @param sdkRoot The location of the SDK root folder. - */ - public LocalSdk(@NonNull File sdkRoot) { - this(); - setLocation(sdkRoot); - } - - /** - * Creates an initial LocalSdk instance with an unknown location. - * This is designed for unit tests to override the {@link LegacyFileOp} being used. - * - * @param LegacyFileOp The alternate {@link LegacyFileOp} to use for all file-based interactions. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - public LocalSdk(@NonNull IFileOp LegacyFileOp) { - mFileOp = LegacyFileOp; - } - - /* - * Returns the current IFileOp being used. - */ - @NonNull - public IFileOp getFileOp() { - return mFileOp; - } - - /** - * Sets or changes the SDK root location. This also clears any cached information. - * - * @param sdkRoot The location of the SDK root folder. - */ - public void setLocation(@NonNull File sdkRoot) { - assert sdkRoot != null; - mSdkRoot = sdkRoot; - clearLocalPkg(PkgType.PKG_ALL); - } - - /** - * Location of the SDK. Maybe null. Can be changed. - * - * @return The location of the SDK. Null if not initialized yet. - */ - @Nullable - public File getLocation() { - return mSdkRoot; - } - - /** - * Location of the SDK. Maybe null. Can be changed. - * The getLocation() API replaces this function. - * @return The location of the SDK. Null if not initialized yet. - */ - @Deprecated - @Nullable - public String getPath() { - return mSdkRoot != null ? mSdkRoot.getPath() : null; - } - - /** - * Clear the tracked visited folders & the cached {@link LocalPkgInfo} for the - * given filter types. - * - * @param filters A set of PkgType constants or {@link PkgType#PKG_ALL} to clear everything. - */ - public void clearLocalPkg(@NonNull EnumSet filters) { - mLegacyBuildTools = null; - - synchronized (mLocalPackages) { - for (PkgType filter : filters) { - mVisitedDirs.removeAll(filter); - mLocalPackages.removeAll(filter); - } - - // Clear the targets if the platforms or addons are being cleared - if (filters.contains(PkgType.PKG_PLATFORM) || filters.contains(PkgType.PKG_ADDON)) { - mCachedMissingTargets = null; - mCachedTargets = null; - } - } - } - - /** - * Check the tracked visited folders to see if anything has changed for the - * requested filter types. - * This does not refresh or reload any package information. - * - * @param filters A set of PkgType constants or {@link PkgType#PKG_ALL} to clear everything. - */ - public boolean hasChanged(@NonNull EnumSet filters) { - for (PkgType filter : filters) { - Collection dirInfos; - synchronized (mLocalPackages) { - dirInfos = mVisitedDirs.get(filter); - for(LocalDirInfo dirInfo : dirInfos) { - if (dirInfo.hasChanged()) { - return true; - } - } - } - } - - return false; - } - - //--------- Generic querying --------- - - - /** - * Retrieves information on a package identified by an {@link IPkgDesc}. - * - * @param descriptor {@link IPkgDesc} describing a package. - * @return The first package found with the same descriptor or null. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull IPkgDesc descriptor) { - - for (LocalPkgInfo pkg : getPkgsInfos(EnumSet.of(descriptor.getType()))) { - IPkgDesc d = pkg.getDesc(); - if (d.equals(descriptor)) { - return pkg; - } - } - - return null; - } - - /** - * Retrieves information on a package identified by an {@link AndroidVersion}. - * - * Note: don't use this for {@link PkgType#PKG_SYS_IMAGE} since there can be more than - * one ABI and this method only returns a single package per filter type. - * - * @param filter {@link PkgType#PKG_PLATFORM}, {@link PkgType#PKG_SAMPLE} - * or {@link PkgType#PKG_SOURCE}. - * @param version The {@link AndroidVersion} specific for this package type. - * @return An existing package information or null if not found. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull PkgType filter, @NonNull AndroidVersion version) { - assert filter == PkgType.PKG_PLATFORM || - filter == PkgType.PKG_SAMPLE || - filter == PkgType.PKG_SOURCE; - - for (LocalPkgInfo pkg : getPkgsInfos(filter)) { - IPkgDesc d = pkg.getDesc(); - if (d.hasAndroidVersion() && d.getAndroidVersion().equals(version)) { - return pkg; - } - } - - return null; - } - - /** - * Retrieves information on a package identified by its {@link FullRevision}. - *

- * Note that {@link PkgType#PKG_TOOLS} and {@link PkgType#PKG_PLATFORM_TOOLS} - * are unique in a local SDK so you'll want to use {@link #getPkgInfo(PkgType)} - * to retrieve them instead. - * - * @param filter {@link PkgType#PKG_BUILD_TOOLS}. - * @param revision The {@link FullRevision} uniquely identifying this package. - * @return An existing package information or null if not found. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull PkgType filter, @NonNull FullRevision revision) { - - assert filter == PkgType.PKG_BUILD_TOOLS; - - for (LocalPkgInfo pkg : getPkgsInfos(filter)) { - IPkgDesc d = pkg.getDesc(); - if (d.hasFullRevision() && d.getFullRevision().equals(revision)) { - return pkg; - } - } - return null; - } - - /** - * Retrieves information on a package identified by its {@link String} path. - *

- * For add-ons and platforms, the path is the target hash string - * (see {@link AndroidTargetHash} for helpers methods to generate this string.) - * - * @param filter {@link PkgType#PKG_ADDON}, {@link PkgType#PKG_PLATFORM}. - * @param path The vendor/path uniquely identifying this package. - * @return An existing package information or null if not found. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull PkgType filter, @NonNull String path) { - - assert filter == PkgType.PKG_ADDON || - filter == PkgType.PKG_PLATFORM; - - for (LocalPkgInfo pkg : getPkgsInfos(filter)) { - IPkgDesc d = pkg.getDesc(); - if (d.hasPath() && path.equals(d.getPath())) { - return pkg; - } - } - return null; - } - - /** - * Retrieves information on a package identified by both vendor and path strings. - *

- * For add-ons the path is target hash string - * (see {@link AndroidTargetHash} for helpers methods to generate this string.) - * - * @param filter {@link PkgType#PKG_EXTRA}, {@link PkgType#PKG_ADDON}. - * @param vendor The vendor id of the extra package. - * @param path The path uniquely identifying this package for its vendor. - * @return An existing package information or null if not found. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull PkgType filter, - @NonNull String vendor, - @NonNull String path) { - - assert filter == PkgType.PKG_EXTRA || - filter == PkgType.PKG_ADDON; - - for (LocalPkgInfo pkg : getPkgsInfos(filter)) { - IPkgDesc d = pkg.getDesc(); - if (d.hasVendor() && vendor.equals(d.getVendor().getId())) { - if (d.hasPath() && path.equals(d.getPath())) { - return pkg; - } - } - } - return null; - } - - /** - * Retrieves information on an extra package identified by its {@link String} vendor/path. - * - * @param vendor The vendor id of the extra package. - * @param path The path uniquely identifying this package for its vendor. - * @return An existing extra package information or null if not found. - */ - @Nullable - public LocalExtraPkgInfo getExtra(@NonNull String vendor, @NonNull String path) { - return (LocalExtraPkgInfo) getPkgInfo(PkgType.PKG_EXTRA, vendor, path); - } - - /** - * For unique local packages. - * Returns the cached LocalPkgInfo for the requested type. - * Loads it from disk if not cached. - * - * @param filter {@link PkgType#PKG_TOOLS} or {@link PkgType#PKG_PLATFORM_TOOLS} - * or {@link PkgType#PKG_DOC}. - * @return null if the package is not installed. - */ - @Nullable - public LocalPkgInfo getPkgInfo(@NonNull PkgType filter) { - if (filter != PkgType.PKG_TOOLS && - filter != PkgType.PKG_PLATFORM_TOOLS && - filter != PkgType.PKG_DOC && - filter != PkgType.PKG_NDK) { - assert false; - return null; - } - - LocalPkgInfo info = null; - synchronized (mLocalPackages) { - Collection existing = mLocalPackages.get(filter); - assert existing.size() <= 1; - if (!existing.isEmpty()) { - return existing.iterator().next(); - } - - File uniqueDir = new File(mSdkRoot, filter.getFolderName()); - - if (!mVisitedDirs.containsEntry(filter, new LocalDirInfo.MapComparator(uniqueDir))) { - switch(filter) { - case PKG_TOOLS: - info = scanTools(uniqueDir); - break; - case PKG_PLATFORM_TOOLS: - info = scanPlatformTools(uniqueDir); - break; - case PKG_DOC: - info = scanDoc(uniqueDir); - break; - case PKG_NDK: - info = scanNdk(uniqueDir); - default: - break; - } - } - - // Whether we have found a valid pkg or not, this directory has been visited. - mVisitedDirs.put(filter, new LocalDirInfo(mFileOp, uniqueDir)); - - if (info != null) { - mLocalPackages.put(filter, info); - } - } - - return info; - } - - /** - * Retrieve all the info about the requested package type. - * This is used for the package types that have one or more instances, each with different - * versions. - * The resulting array is sorted according to the PkgInfo's sort order. - *

- * Note: you can use this with {@link PkgType#PKG_TOOLS}, {@link PkgType#PKG_PLATFORM_TOOLS} and - * {@link PkgType#PKG_DOC} but since there can only be one package of these types, it is - * more efficient to use {@link #getPkgInfo(PkgType)} to query them. - * - * @param filter One of {@link PkgType} constants. - * @return A list (possibly empty) of matching installed packages. Never returns null. - */ - @NonNull - public LocalPkgInfo[] getPkgsInfos(@NonNull PkgType filter) { - return getPkgsInfos(EnumSet.of(filter)); - } - - /** - * Retrieve all the info about the requested package types. - * This is used for the package types that have one or more instances, each with different - * versions. - * The resulting array is sorted according to the PkgInfo's sort order. - *

- * To force the LocalSdk parser to load everything, simply call this method - * with the {@link PkgType#PKG_ALL} argument to load all the known package types. - *

- * Note: you can use this with {@link PkgType#PKG_TOOLS}, {@link PkgType#PKG_PLATFORM_TOOLS} and - * {@link PkgType#PKG_DOC} but since there can only be one package of these types, it is - * more efficient to use {@link #getPkgInfo(PkgType)} to query them. - * - * @param filters One or more of {@link PkgType#PKG_ADDON}, {@link PkgType#PKG_PLATFORM}, - * {@link PkgType#PKG_BUILD_TOOLS}, {@link PkgType#PKG_EXTRA}, - * {@link PkgType#PKG_SOURCE}, {@link PkgType#PKG_SYS_IMAGE} - * @return A list (possibly empty) of matching installed packages. Never returns null. - */ - @NonNull - public LocalPkgInfo[] getPkgsInfos(@NonNull EnumSet filters) { - List list = Lists.newArrayList(); - - for (PkgType filter : filters) { - if (filter == PkgType.PKG_TOOLS || - filter == PkgType.PKG_PLATFORM_TOOLS || - filter == PkgType.PKG_DOC || - filter == PkgType.PKG_NDK) { - LocalPkgInfo info = getPkgInfo(filter); - if (info != null) { - list.add(info); - } - } else { - synchronized (mLocalPackages) { - Collection existing = mLocalPackages.get(filter); - assert existing != null; // Multimap returns an empty set if not found - - if (!existing.isEmpty()) { - list.addAll(existing); - continue; - } - - File subDir = new File(mSdkRoot, filter.getFolderName()); - - if (!mVisitedDirs.containsEntry(filter, new LocalDirInfo.MapComparator(subDir))) { - switch(filter) { - case PKG_BUILD_TOOLS: - scanBuildTools(subDir, existing); - break; - - case PKG_PLATFORM: - scanPlatforms(subDir, existing); - break; - - case PKG_SYS_IMAGE: - scanSysImages(subDir, existing, false); - break; - - case PKG_ADDON_SYS_IMAGE: - scanSysImages(subDir, existing, true); - break; - - case PKG_ADDON: - scanAddons(subDir, existing); - break; - - case PKG_SAMPLE: - scanSamples(subDir, existing); - break; - - case PKG_SOURCE: - scanSources(subDir, existing); - break; - - case PKG_EXTRA: - scanExtras(subDir, existing); - break; - - case PKG_TOOLS: - case PKG_PLATFORM_TOOLS: - case PKG_DOC: - case PKG_NDK: - break; - default: - throw new IllegalArgumentException( - "Unsupported pkg type " + filter.toString()); - } - mVisitedDirs.put(filter, new LocalDirInfo(mFileOp, subDir)); - list.addAll(existing); - } - } - } - } - - Collections.sort(list); - return list.toArray(new LocalPkgInfo[list.size()]); - } - - //---------- Package-specific querying -------- - - /** - * Returns the {@link BuildToolInfo} for the given revision. - * - * @param revision The requested revision. - * @return A {@link BuildToolInfo}. Can be null if {@code revision} is null or is - * not part of the known set returned by {@code getPkgsInfos(PkgType.PKG_BUILD_TOOLS)}. - */ - @Nullable - public BuildToolInfo getBuildTool(@Nullable FullRevision revision) { - LocalPkgInfo pkg = getPkgInfo(PkgType.PKG_BUILD_TOOLS, revision); - if (pkg instanceof LocalBuildToolPkgInfo) { - return ((LocalBuildToolPkgInfo) pkg).getBuildToolInfo(); - } - return null; - } - - /** - * Returns the highest build-tool revision known, or null if there are are no build-tools. - *

- * If no specific build-tool package is installed but the platform-tools is lower than 17, - * then this creates and returns a "legacy" built-tool package using platform-tools. - * (We only split build-tools out of platform-tools starting with revision 17, - * before they were both the same thing.) - * - * @return The highest build-tool revision known, or null. - */ - @Nullable - public BuildToolInfo getLatestBuildTool() { - if (mLegacyBuildTools != null) { - return mLegacyBuildTools; - } - - LocalPkgInfo[] pkgs = getPkgsInfos(PkgType.PKG_BUILD_TOOLS); - - if (pkgs.length == 0) { - LocalPkgInfo ptPkg = getPkgInfo(PkgType.PKG_PLATFORM_TOOLS); - if (ptPkg instanceof LocalPlatformToolPkgInfo && - ptPkg.getDesc().getFullRevision().compareTo(new FullRevision(17)) < 0) { - // older SDK, create a compatible build-tools - mLegacyBuildTools = createLegacyBuildTools((LocalPlatformToolPkgInfo) ptPkg); - return mLegacyBuildTools; - } - return null; - } - - assert pkgs.length > 0; - - // Note: the pkgs come from a TreeMultimap so they should already be sorted. - // Just in case, sort them again. - Arrays.sort(pkgs); - - // LocalBuildToolPkgInfo's comparator sorts on its FullRevision so we just - // need to take the latest element. - LocalPkgInfo pkg = pkgs[pkgs.length - 1]; - if (pkg instanceof LocalBuildToolPkgInfo) { - return ((LocalBuildToolPkgInfo) pkg).getBuildToolInfo(); - } - - return null; - } - - @NonNull - private BuildToolInfo createLegacyBuildTools(@NonNull LocalPlatformToolPkgInfo ptInfo) { - File platformTools = new File(getLocation(), SdkConstants.FD_PLATFORM_TOOLS); - File platformToolsLib = ptInfo.getLocalDir(); - File platformToolsRs = new File(platformTools, SdkConstants.FN_FRAMEWORK_RENDERSCRIPT); - - return new BuildToolInfo( - ptInfo.getDesc().getFullRevision(), - platformTools, - new File(platformTools, SdkConstants.FN_AAPT), - new File(platformTools, SdkConstants.FN_AIDL), - new File(platformTools, SdkConstants.FN_DX), - new File(platformToolsLib, SdkConstants.FN_DX_JAR), - new File(platformTools, SdkConstants.FN_RENDERSCRIPT), - new File(platformToolsRs, SdkConstants.FN_FRAMEWORK_INCLUDE), - new File(platformToolsRs, SdkConstants.FN_FRAMEWORK_INCLUDE_CLANG), - null, - null, - null, - null, - new File(platformTools, SdkConstants.FN_ZIPALIGN)); - } - - /** - * Returns the targets (platforms & addons) that are available in the SDK. - * The target list is created on demand the first time then cached. - * It will not refreshed unless {@link #clearLocalPkg} is called to clear platforms - * and/or add-ons. - *

- * The array can be empty but not null. - */ - @NonNull - public IAndroidTarget[] getTargets() { - synchronized (mLocalPackages) { - if (mCachedTargets == null) { - List result = Lists.newArrayList(); - LocalPkgInfo[] pkgsInfos = getPkgsInfos(EnumSet.of(PkgType.PKG_PLATFORM, - PkgType.PKG_ADDON)); - for (LocalPkgInfo info : pkgsInfos) { - assert info instanceof LocalPlatformPkgInfo; - IAndroidTarget target = ((LocalPlatformPkgInfo) info).getAndroidTarget(); - if (target != null) { - result.add(target); - } - } - mCachedTargets = result; - } - return mCachedTargets.toArray(new IAndroidTarget[mCachedTargets.size()]); - } - } - - public IAndroidTarget[] getTargets(boolean includeMissing) { - IAndroidTarget[] result = getTargets(); - if (includeMissing) { - result = ObjectArrays.concat(result, getMissingTargets(), IAndroidTarget.class); - } - return result; - } - - @NonNull - public IAndroidTarget[] getMissingTargets() { - synchronized (mLocalPackages) { - if (mCachedMissingTargets == null) { - Map result = Maps.newHashMap(); - Set seen = Sets.newHashSet(); - for (IAndroidTarget target : getTargets()) { - Collections.addAll(seen, target.getSystemImages()); - } - for (LocalPkgInfo local : getPkgsInfos(PkgType.PKG_ADDON_SYS_IMAGE)) { - LocalAddonSysImgPkgInfo info = (LocalAddonSysImgPkgInfo)local; - ISystemImage image = info.getSystemImage(); - if (!seen.contains(image)) { - addOrphanedSystemImage(image, info.getDesc(), result); - } - } - for (LocalPkgInfo local : getPkgsInfos(PkgType.PKG_SYS_IMAGE)) { - LocalSysImgPkgInfo info = (LocalSysImgPkgInfo)local; - ISystemImage image = info.getSystemImage(); - if (!seen.contains(image)) { - addOrphanedSystemImage(image, info.getDesc(), result); - } - } - mCachedMissingTargets = result.keySet(); - } - return mCachedMissingTargets.toArray(new IAndroidTarget[mCachedMissingTargets.size()]); - } - } - - private static void addOrphanedSystemImage(ISystemImage image, IPkgDesc desc, Map targets) { - IdDisplay vendor = desc.getVendor(); - MissingTarget target = new MissingTarget(vendor == null ? null : vendor.getDisplay(), desc.getTag().getDisplay(), desc.getAndroidVersion()); - MissingTarget existing = targets.get(target); - if (existing == null) { - existing = target; - targets.put(target, target); - } - existing.addSystemImage(image); - } - - /** - * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}. - * - * @param hash the {@link IAndroidTarget} hash string. - * @return The matching {@link IAndroidTarget} or null. - */ - @Nullable - public IAndroidTarget getTargetFromHashString(@Nullable String hash) { - if (hash != null) { - IAndroidTarget[] targets = getTargets(true); - for (IAndroidTarget target : targets) { - if (target != null && hash.equals(AndroidTargetHash.getTargetHashString(target))) { - return target; - } - } - } - return null; - } - - // ------------- - - /** - * Try to find a tools package at the given location. - * Returns null if not found. - */ - private LocalToolPkgInfo scanTools(File toolFolder) { - // Can we find some properties? - Properties props = parseProperties(new File(toolFolder, SdkConstants.FN_SOURCE_PROP)); - FullRevision rev = PackageParserUtils.getPropertyFull(props, PkgProps.PKG_REVISION); - if (rev == null) { - return null; - } - - FullRevision minPlatToolsRev = - PackageParserUtils.getPropertyFull(props, PkgProps.MIN_PLATFORM_TOOLS_REV); - if (minPlatToolsRev == null) { - minPlatToolsRev = FullRevision.NOT_SPECIFIED; - } - - LocalToolPkgInfo info = new LocalToolPkgInfo(this, toolFolder, props, rev, minPlatToolsRev); - - // We're not going to check that all tools are present. At the very least - // we should expect to find android and an emulator adapted to the current OS. - boolean hasEmulator = false; - boolean hasAndroid = false; - String android1 = SdkConstants.androidCmdName().replace(".bat", ".exe"); - String android2 = android1.indexOf('.') == -1 ? null : android1.replace(".exe", ".bat"); - File[] files = mFileOp.listFiles(toolFolder); - for (File file : files) { - String name = file.getName(); - if (SdkConstants.FN_EMULATOR.equals(name)) { - hasEmulator = true; - } - if (android1.equals(name) || (android2 != null && android2.equals(name))) { - hasAndroid = true; - } - } - if (!hasAndroid) { - info.appendLoadError("Missing %1$s", SdkConstants.androidCmdName()); - } - if (!hasEmulator) { - info.appendLoadError("Missing %1$s", SdkConstants.FN_EMULATOR); - } - - return info; - } - - /** - * Try to find a platform-tools package at the given location. - * Returns null if not found. - */ - private LocalPlatformToolPkgInfo scanPlatformTools(File ptFolder) { - // Can we find some properties? - Properties props = parseProperties(new File(ptFolder, SdkConstants.FN_SOURCE_PROP)); - FullRevision rev = PackageParserUtils.getPropertyFull(props, PkgProps.PKG_REVISION); - if (rev == null) { - return null; - } - - LocalPlatformToolPkgInfo info = new LocalPlatformToolPkgInfo(this, ptFolder, props, rev); - return info; - } - - /** - * Try to find a docs package at the given location. - * Returns null if not found. - */ - private LocalDocPkgInfo scanDoc(File docFolder) { - // Can we find some properties? - Properties props = parseProperties(new File(docFolder, SdkConstants.FN_SOURCE_PROP)); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - return null; - } - - try { - AndroidVersion vers = new AndroidVersion(props); - LocalDocPkgInfo info = new LocalDocPkgInfo(this, docFolder, props, vers, rev); - - // To start with, a doc folder should have an "index.html" to be acceptable. - // We don't actually check the content of the file. - if (!mFileOp.isFile(new File(docFolder, "index.html"))) { - info.appendLoadError("Missing index.html"); - } - return info; - - } catch (AndroidVersionException e) { - return null; // skip invalid or missing android version. - } - } - - /** - * Try to find an NDK package at the given location. - * Returns null if not found. - */ - @Nullable - private LocalNdkPkgInfo scanNdk(@NonNull File ndkFolder) { - // Can we find some properties? - Properties props = parseProperties(new File(ndkFolder, SdkConstants.FN_SOURCE_PROP)); - FullRevision rev = PackageParserUtils.getPropertyFull(props, PkgProps.PKG_REVISION); - if (rev == null) { - return null; - } - - return new LocalNdkPkgInfo(this, ndkFolder, props, rev); - } - - - /** - * Helper used by scanXyz methods below to check whether a directory should be visited. - * It can be skipped if it's not a directory or if it's already marked as visited in - * mVisitedDirs for the given package type -- in which case the directory is added to - * the visited map. - * - * @param pkgType The package type being scanned. - * @param directory The file or directory to check. - * @return False if directory can/should be skipped. - * True if directory should be visited, in which case it's registered in mVisitedDirs. - */ - private boolean shouldVisitDir(@NonNull PkgType pkgType, @NonNull File directory) { - if (!mFileOp.isDirectory(directory)) { - return false; - } - synchronized (mLocalPackages) { - if (mVisitedDirs.containsEntry(pkgType, new LocalDirInfo.MapComparator(directory))) { - return false; - } - mVisitedDirs.put(pkgType, new LocalDirInfo(mFileOp, directory)); - } - return true; - } - - private void scanBuildTools(File collectionDir, Collection outCollection) { - // The build-tool root folder contains a list of per-revision folders. - for (File buildToolDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_BUILD_TOOLS, buildToolDir)) { - continue; - } - - Properties props = parseProperties(new File(buildToolDir, SdkConstants.FN_SOURCE_PROP)); - FullRevision rev = PackageParserUtils.getPropertyFull(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - BuildToolInfo btInfo = new BuildToolInfo(rev, buildToolDir); - LocalBuildToolPkgInfo pkgInfo = - new LocalBuildToolPkgInfo(this, buildToolDir, props, rev, btInfo); - outCollection.add(pkgInfo); - } - } - - private void scanPlatforms(File collectionDir, Collection outCollection) { - for (File platformDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_PLATFORM, platformDir)) { - continue; - } - - Properties props = parseProperties(new File(platformDir, SdkConstants.FN_SOURCE_PROP)); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - FullRevision minToolsRev = - PackageParserUtils.getPropertyFull(props, PkgProps.MIN_TOOLS_REV); - if (minToolsRev == null) { - minToolsRev = FullRevision.NOT_SPECIFIED; - } - - try { - AndroidVersion vers = new AndroidVersion(props); - - LocalPlatformPkgInfo pkgInfo = - new LocalPlatformPkgInfo(this, platformDir, props, vers, rev, minToolsRev); - outCollection.add(pkgInfo); - - } catch (AndroidVersionException e) { - continue; // skip invalid or missing android version. - } - } - } - - private void scanAddons(File collectionDir, Collection outCollection) { - for (File addonDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_ADDON, addonDir)) { - continue; - } - - Properties props = parseProperties(new File(addonDir, SdkConstants.FN_SOURCE_PROP)); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - try { - AndroidVersion vers = new AndroidVersion(props); - - // Starting with addon-4.xsd, we have vendor-id and name-id available - // in the add-on source properties so we'll use that directly. - - String nameId = props.getProperty(PkgProps.ADDON_NAME_ID); - String nameDisp = props.getProperty(PkgProps.ADDON_NAME_DISPLAY); - String vendorId = props.getProperty(PkgProps.ADDON_VENDOR_ID); - String vendorDisp = props.getProperty(PkgProps.ADDON_VENDOR_DISPLAY); - - if (nameId == null) { - // Support earlier add-ons that only had a name display attribute - nameDisp = props.getProperty(PkgProps.ADDON_NAME, "Unknown"); - nameId = LocalAddonPkgInfo.sanitizeDisplayToNameId(nameDisp); - } - - if (nameId != null && nameDisp == null) { - nameDisp = LocalExtraPkgInfo.getPrettyName(null, nameId); - } - - if (vendorId != null && vendorDisp == null) { - vendorDisp = LocalExtraPkgInfo.getPrettyName(null, nameId); - } - - if (vendorId == null) { - // Support earlier add-ons that only had a vendor display attribute - vendorDisp = props.getProperty(PkgProps.ADDON_VENDOR, "Unknown"); - vendorId = LocalAddonPkgInfo.sanitizeDisplayToNameId(vendorDisp); - } - - LocalAddonPkgInfo pkgInfo = new LocalAddonPkgInfo( - this, addonDir, props, vers, rev, - new IdDisplay(vendorId, vendorDisp), - new IdDisplay(nameId, nameDisp)); - outCollection.add(pkgInfo); - - } catch (AndroidVersionException e) { - continue; // skip invalid or missing android version. - } - } - } - - private void scanSysImages( - File collectionDir, - Collection outCollection, - boolean scanAddons) { - List propFiles = Lists.newArrayList(); - PkgType type = scanAddons ? PkgType.PKG_ADDON_SYS_IMAGE : PkgType.PKG_SYS_IMAGE; - - // Create a list of folders that contains a source.properties file matching these patterns: - // sys-img/target/tag/abi - // sys-img/target/abis - // sys-img/add-on-target/abi - // sys-img/target/add-on/abi - for (File platformDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(type, platformDir)) { - continue; - } - - for (File dir1 : mFileOp.listFiles(platformDir)) { - // dir1 might be either a tag or an abi folder. - if (!shouldVisitDir(type, dir1)) { - continue; - } - - File prop1 = new File(dir1, SdkConstants.FN_SOURCE_PROP); - if (mFileOp.isFile(prop1)) { - // dir1 was a legacy abi folder. - if (!propFiles.contains(prop1)) { - propFiles.add(prop1); - } - } else { - File[] dir1Files = mFileOp.listFiles(dir1); - for (File dir2 : dir1Files) { - // dir2 should be an abi folder in a tag folder. - if (!shouldVisitDir(type, dir2)) { - continue; - } - - File prop2 = new File(dir2, SdkConstants.FN_SOURCE_PROP); - if (mFileOp.isFile(prop2)) { - if (!propFiles.contains(prop2)) { - propFiles.add(prop2); - } - } - } - } - } - } - - for (File propFile : propFiles) { - Properties props = parseProperties(propFile); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - try { - AndroidVersion vers = new AndroidVersion(props); - - IdDisplay tag = LocalSysImgPkgInfo.extractTagFromProps(props); - String vendorId = props.getProperty(PkgProps.ADDON_VENDOR_ID, null); - File abiDir = propFile.getParentFile(); - - if (vendorId == null && !scanAddons) { - LocalSysImgPkgInfo pkgInfo = - new LocalSysImgPkgInfo(this, abiDir, props, vers, tag, abiDir.getName(), rev); - outCollection.add(pkgInfo); - - } else if (vendorId != null && scanAddons) { - String vendorDisp = props.getProperty(PkgProps.ADDON_VENDOR_DISPLAY, vendorId); - IdDisplay vendor = new IdDisplay(vendorId, vendorDisp); - - LocalAddonSysImgPkgInfo pkgInfo = - new LocalAddonSysImgPkgInfo( - this, abiDir, props, vers, vendor, tag, abiDir.getName(), rev); - outCollection.add(pkgInfo); - } - - } catch (AndroidVersionException e) { - continue; // skip invalid or missing android version. - } - } - } - - private void scanSamples(File collectionDir, Collection outCollection) { - for (File platformDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_SAMPLE, platformDir)) { - continue; - } - - Properties props = parseProperties(new File(platformDir, SdkConstants.FN_SOURCE_PROP)); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - FullRevision minToolsRev = - PackageParserUtils.getPropertyFull(props, PkgProps.MIN_TOOLS_REV); - if (minToolsRev == null) { - minToolsRev = FullRevision.NOT_SPECIFIED; - } - - try { - AndroidVersion vers = new AndroidVersion(props); - - LocalSamplePkgInfo pkgInfo = - new LocalSamplePkgInfo(this, platformDir, props, vers, rev, minToolsRev); - outCollection.add(pkgInfo); - } catch (AndroidVersionException e) { - continue; // skip invalid or missing android version. - } - } - } - - private void scanSources(File collectionDir, Collection outCollection) { - // The build-tool root folder contains a list of per-revision folders. - for (File platformDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_SOURCE, platformDir)) { - continue; - } - - Properties props = parseProperties(new File(platformDir, SdkConstants.FN_SOURCE_PROP)); - MajorRevision rev = PackageParserUtils.getPropertyMajor(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - try { - AndroidVersion vers = new AndroidVersion(props); - - LocalSourcePkgInfo pkgInfo = - new LocalSourcePkgInfo(this, platformDir, props, vers, rev); - outCollection.add(pkgInfo); - } catch (AndroidVersionException e) { - continue; // skip invalid or missing android version. - } - } - } - - private void scanExtras(File collectionDir, Collection outCollection) { - for (File vendorDir : mFileOp.listFiles(collectionDir)) { - if (!shouldVisitDir(PkgType.PKG_EXTRA, vendorDir)) { - continue; - } - - for (File extraDir : mFileOp.listFiles(vendorDir)) { - if (!shouldVisitDir(PkgType.PKG_EXTRA, extraDir)) { - continue; - } - - Properties props = parseProperties(new File(extraDir, SdkConstants.FN_SOURCE_PROP)); - NoPreviewRevision rev = - PackageParserUtils.getPropertyNoPreview(props, PkgProps.PKG_REVISION); - if (rev == null) { - continue; // skip, no revision - } - - String oldPaths = - PackageParserUtils.getProperty(props, PkgProps.EXTRA_OLD_PATHS, null); - - String vendorId = vendorDir.getName(); - String vendorDisp = props.getProperty(PkgProps.EXTRA_VENDOR_DISPLAY); - if (vendorDisp == null || vendorDisp.isEmpty()) { - vendorDisp = vendorId; - } - - String displayName = props.getProperty(PkgProps.EXTRA_NAME_DISPLAY, null); - - LocalExtraPkgInfo pkgInfo = new LocalExtraPkgInfo( - this, - extraDir, - props, - new IdDisplay(vendorId, vendorDisp), - extraDir.getName(), - displayName, - PkgDescExtra.convertOldPaths(oldPaths), - rev); - outCollection.add(pkgInfo); - } - } - } - - /** - * Parses the given file as properties file if it exists. - * Returns null if the file does not exist, cannot be parsed or has no properties. - */ - private Properties parseProperties(File propsFile) { - InputStream fis = null; - try { - if (mFileOp.exists(propsFile)) { - fis = mFileOp.newFileInputStream(propsFile); - - Properties props = new Properties(); - props.load(fis); - - // To be valid, there must be at least one property in it. - if (!props.isEmpty()) { - return props; - } - } - } catch (IOException e) { - // Ignore - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) {} - } - } - return null; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSourcePkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSourcePkgInfo.java deleted file mode 100644 index eb822de1..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSourcePkgInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -/** - * Local source package, for a given platform's {@link AndroidVersion}. - * The package itself has a major revision. - * There should be only one for a given android platform version. - */ -public class LocalSourcePkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDesc mDesc; - - public LocalSourcePkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @NonNull MajorRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newSource(version, revision).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSysImgPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSysImgPkgInfo.java deleted file mode 100644 index 0f6cdad5..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalSysImgPkgInfo.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SystemImage; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.descriptors.PkgDesc; -import com.google.common.base.Objects; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Properties; - -/** - * Local system-image package, for a given platform's {@link AndroidVersion} - * and given ABI. - * The package itself has a major revision. - * There should be only one for a given android platform version & ABI. - */ -public class LocalSysImgPkgInfo extends LocalPkgInfo { - - - @NonNull - private final IPkgDesc mDesc; - - public LocalSysImgPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull AndroidVersion version, - @Nullable IdDisplay tag, - @NonNull String abi, - @NonNull MajorRevision revision) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newSysImg(version, tag, abi, revision).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } - - /** - * Extracts the tag id & display from the properties. - * If missing, uses the "default" tag id. - */ - @NonNull - public static IdDisplay extractTagFromProps(Properties props) { - if (props != null) { - String tagId = props.getProperty(PkgProps.SYS_IMG_TAG_ID, SystemImage.DEFAULT_TAG.getId()); - String tagDisp = props.getProperty(PkgProps.SYS_IMG_TAG_DISPLAY, ""); //$NON-NLS-1$ - if (tagDisp == null || tagDisp.isEmpty()) { - tagDisp = tagIdToDisplay(tagId); - } - assert tagId != null; - assert tagDisp != null; - return new IdDisplay(tagId, tagDisp); - } - return SystemImage.DEFAULT_TAG; - } - - /** - * Computes a display-friendly tag string based on the tag id. - * This is typically used when there's no tag-display attribute. - * - * @param tagId A non-null tag id to sanitize for display. - * @return The tag id with all non-alphanum symbols replaced by spaces and trimmed. - */ - @NonNull - public static String tagIdToDisplay(@NonNull String tagId) { - String name; - name = tagId.replaceAll("[^A-Za-z0-9]+", " "); //$NON-NLS-1$ //$NON-NLS-2$ - name = name.replaceAll(" +", " "); //$NON-NLS-1$ //$NON-NLS-2$ - name = name.trim(); - - if (!name.isEmpty()) { - char c = name.charAt(0); - if (!Character.isUpperCase(c)) { - StringBuilder sb = new StringBuilder(name); - sb.replace(0, 1, String.valueOf(c).toUpperCase(Locale.US)); - name = sb.toString(); - } - } - return name; - } - - public SystemImage getSystemImage() { - return getSystemImage(mDesc, getLocalDir(), getLocalSdk().getFileOp()); - } - - static SystemImage getSystemImage(IPkgDesc desc, File localDir, @NonNull IFileOp fileOp) { - final IdDisplay tag = desc.getTag(); - final String abi = desc.getPath(); - List parsedSkins = PackageParserUtils.parseSkinFolder(new File(localDir, SdkConstants.FD_SKINS), fileOp); - File[] skins = LegacyFileOp.EMPTY_FILE_ARRAY; - if (!parsedSkins.isEmpty()) { - skins = parsedSkins.toArray(new File[parsedSkins.size()]); - } - - return new SystemImage( - localDir, - ISystemImage.LocationType.IN_SYSTEM_IMAGE, - tag, - desc.getVendor(), - abi, - skins); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalToolPkgInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalToolPkgInfo.java deleted file mode 100644 index 91306ea3..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/LocalToolPkgInfo.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 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.repository.local; - -import com.android.annotations.NonNull; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.descriptors.IPkgDesc; -import com.android.sdklib.repository.descriptors.PkgDesc; - -import java.io.File; -import java.util.Properties; - -public class LocalToolPkgInfo extends LocalPkgInfo { - - @NonNull - private final IPkgDesc mDesc; - - public LocalToolPkgInfo(@NonNull LocalSdk localSdk, - @NonNull File localDir, - @NonNull Properties sourceProps, - @NonNull FullRevision revision, - @NonNull FullRevision minPlatformToolsRev) { - super(localSdk, localDir, sourceProps); - mDesc = PkgDesc.Builder.newTool(revision, minPlatformToolsRev).create(); - } - - @NonNull - @Override - public IPkgDesc getDesc() { - return mDesc; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/PackageParserUtils.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/PackageParserUtils.java deleted file mode 100644 index e8cc4b2e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/local/PackageParserUtils.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2015 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.repository.local; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.io.IFileOp; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.MajorRevision; -import com.android.sdklib.repository.NoPreviewRevision; -import com.android.sdklib.repository.PkgProps; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; - -/** - * Misc utilities to help extracting elements and attributes out of a repository XML document. - */ -class PackageParserUtils { - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a full - * revision (major.minor.micro.preview). - * - * @param props The properties to parse. - * @return A {@link FullRevision} or null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static FullRevision getPropertyFull( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - FullRevision rev = null; - if (revStr != null) { - try { - rev = FullRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a major - * revision (major integer, no minor/micro/preview parts.) - * - * @param props The properties to parse. - * @return A {@link MajorRevision} or null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static MajorRevision getPropertyMajor( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - MajorRevision rev = null; - if (revStr != null) { - try { - rev = MajorRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - - /** - * Utility method to parse the {@link PkgProps#PKG_REVISION} property as a no-preview - * revision (major.minor.micro integers but no preview part.) - * - * @param props The properties to parse. - * @return A {@link NoPreviewRevision} or - * null if there is no such property or it couldn't be parsed. - * @param propKey The name of the property. Must not be null. - */ - @Nullable - public static NoPreviewRevision getPropertyNoPreview( - @Nullable Properties props, - @NonNull String propKey) { - String revStr = getProperty(props, propKey, null); - - NoPreviewRevision rev = null; - if (revStr != null) { - try { - rev = NoPreviewRevision.parseRevision(revStr); - } catch (NumberFormatException ignore) {} - } - - return rev; - } - - - /** - * Utility method that returns a property from a {@link Properties} object. - * Returns the default value if props is null or if the property is not defined. - * - * @param props The {@link Properties} to search into. - * If null, the default value is returned. - * @param propKey The name of the property. Must not be null. - * @param defaultValue The default value to return if {@code props} is null or if the - * key is not found. Can be null. - * @return The string value of the given key in the properties, or null if the key - * isn't found or if {@code props} is null. - */ - @Nullable - public static String getProperty( - @Nullable Properties props, - @NonNull String propKey, - @Nullable String defaultValue) { - if (props == null) { - return defaultValue; - } - return props.getProperty(propKey, defaultValue); - } - - - /** - * Parses the skin folder and builds the skin list. - * @param skinRootFolder The path to the skin root folder. - */ - @NonNull - public static List parseSkinFolder(@NonNull File skinRootFolder, @NonNull IFileOp fileOp) { - if (fileOp.isDirectory(skinRootFolder)) { - ArrayList skinList = new ArrayList(); - - File[] files = fileOp.listFiles(skinRootFolder); - - for (File skinFolder : files) { - if (fileOp.isDirectory(skinFolder)) { - // check for layout file - File layout = new File(skinFolder, SdkConstants.FN_SKIN_LAYOUT); - - if (fileOp.isFile(layout)) { - // for now we don't parse the content of the layout and - // simply add the directory to the list. - skinList.add(skinFolder); - } - } - } - - Collections.sort(skinList); - return skinList; - } - - return Collections.emptyList(); - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-01.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-01.xsd deleted file mode 100644 index 1d533132..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-01.xsd +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-02.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-02.xsd deleted file mode 100644 index 27fae8b1..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-02.xsd +++ /dev/null @@ -1,361 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-03.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-03.xsd deleted file mode 100644 index ccd00c2a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-03.xsd +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-04.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-04.xsd deleted file mode 100644 index c31efbf5..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-04.xsd +++ /dev/null @@ -1,417 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An ID string for an addon/extra name-id or vendor-id - can only be simple alphanumeric string. - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-05.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-05.xsd deleted file mode 100644 index 546b00d3..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-05.xsd +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An ID string for an addon/extra name-id or vendor-id - can only be simple alphanumeric string. - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-06.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-06.xsd deleted file mode 100644 index 3457aada..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-06.xsd +++ /dev/null @@ -1,472 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An ID string for an addon/extra name-id or vendor-id - can only be simple alphanumeric string. - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and no support for - the optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-07.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-07.xsd deleted file mode 100644 index 3c2c13a4..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addon-07.xsd +++ /dev/null @@ -1,499 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An ID string for an addon/extra name-id or vendor-id - can only be simple alphanumeric string. - - - - - - - - - - - - - - Version information for a layoutlib included in an addon. - . - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and no support for - the optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. It must not be empty. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A CPU bit size filter. - - - - - - - - - - A host OS filter. - - - - - - - - - - - A JVM version number, e.g. "1" or "1.6" or "1.14.15". - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-1.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-1.xsd deleted file mode 100644 index 176fb608..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-1.xsd +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - A simple list of add-ons site. - - - - - - - - - - - - An SDK add-on site. - - - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-2.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-2.xsd deleted file mode 100644 index dde72148..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-addons-list-2.xsd +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - A simple list of add-ons site. - - - - - - - - - - - - - An SDK add-on site. - - - - - - - - - - - - - - - - An SDK sys-img site. - - - - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-01.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-01.xsd deleted file mode 100644 index 38ec3096..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-01.xsd +++ /dev/null @@ -1,381 +0,0 @@ - - - - - - - - - - The repository contains collections of downloadable packages. - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" - content and specifies in which fixed root directory it must be - installed. - The paths "add-ons", "platforms", "tools" and "docs" are - reserved and cannot be used. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-02.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-02.xsd deleted file mode 100644 index ecadc3f9..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-02.xsd +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK add-on package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" - content and specifies in which fixed root directory it must be - installed. - The paths "add-ons", "platforms", "tools" and "docs" are - reserved and cannot be used. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-03.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-03.xsd deleted file mode 100644 index 75d8541f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-03.xsd +++ /dev/null @@ -1,436 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-04.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-04.xsd deleted file mode 100644 index 9b14772a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-04.xsd +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-05.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-05.xsd deleted file mode 100644 index ae8275f0..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-05.xsd +++ /dev/null @@ -1,624 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK extra package. This kind of package is for "free" content. - Such packages are installed in SDK/vendor/path. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-06.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-06.xsd deleted file mode 100644 index bccce69d..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-06.xsd +++ /dev/null @@ -1,608 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-07.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-07.xsd deleted file mode 100644 index ea180709..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-07.xsd +++ /dev/null @@ -1,612 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-08.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-08.xsd deleted file mode 100644 index 0c4ca630..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-08.xsd +++ /dev/null @@ -1,652 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK build-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-09.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-09.xsd deleted file mode 100644 index 1b9d68d4..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-09.xsd +++ /dev/null @@ -1,677 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A tag string for a system image can only be a simple alphanumeric string. - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK build-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-10.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-10.xsd deleted file mode 100644 index 3fc1d929..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-10.xsd +++ /dev/null @@ -1,653 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK build-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A CPU bit size filter. - - - - - - - - - - A host OS filter. - - - - - - - - - - - A JVM version number, e.g. "1" or "1.6" or "1.14.15". - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-11.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-11.xsd deleted file mode 100644 index 8e9f736a..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-repository-11.xsd +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable packages. - - - - - - - - - - - - - - - - - - - - An NDK package. - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Version information for a layoutlib included in a platform. - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - Sources for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK platform-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK build-tool package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK doc package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An SDK sample package. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - One path segment for the install path of an extra element. - It must be a single-segment path. - - - - - - - - - - - A semi-colon separated list of a segmentTypes. - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A full revision, with a major.minor.micro and an - optional preview number. The major number is mandatory. - - - - - - - - - - - - - - - - - - - - - A collection of file paths available in an <extra> package - that can be installed in an Android project. - If present, the <project-files> collection must contain at least one path. - Each path is relative to the root directory of the package. - - - - - - - - - - - - - - A CPU bit size filter. - - - - - - - - - - A host OS filter. - - - - - - - - - - - A JVM version number, e.g. "1" or "1.6" or "1.14.15". - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-stats-1.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-stats-1.xsd deleted file mode 100644 index 2944b124..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-stats-1.xsd +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - A simple list of platform stats. - - - - - - - - - - - - - Stats information for a given Android platform. - The api-level acts as a key, and it is epxected there should only - be one platform listed with the same API-level. - - - - - - - - - - - - - - - - - - - - - - - A decimal percentage, between 0.0 and 100.0%. - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-01.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-01.xsd deleted file mode 100644 index 005b4316..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-01.xsd +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable system images. - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-02.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-02.xsd deleted file mode 100644 index a1c16a32..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-02.xsd +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable system images. - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An tag string for a system image can only be simple alphanumeric string. - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-03.xsd b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-03.xsd deleted file mode 100644 index 9b63c010..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/sdk-sys-img-03.xsd +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - - - - - - - The repository contains a collection of downloadable system images. - - - - - - - - - - - - - - - System Image for a platform. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Indicates a system-image is tied to an add-on and which one - (the combo tag-id + vendor-id uniquely identifies the add-on.) - Mandatory for add-on system-images. - Must not be present for platform system-images. - - - - - - - - - - - - - - - An tag string for a system image can only be simple alphanumeric string. - - - - - - - - - - - - - The ABI of a platform's system image. - - - - - - - - - - - - - - - - - - - A license definition. Such a license must be used later as a reference - using a uses-license element in one of the package elements. - - - - - - - - - - - - - - - - - Describes the license used by a package. The license MUST be defined - using a license node and referenced using the ref attribute of the - license element inside a package. - - - - - - - - - - - - A collection of files that can be downloaded for a given architecture. - The <archives> node is mandatory in the repository packages and the - collection must have at least one <archive> declared. - Each archive is a zip file that will be unzipped in a location that depends - on its package type. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A CPU bit size filter. - - - - - - - - - - A host OS filter. - - - - - - - - - - - A JVM version number, e.g. "1" or "1.6" or "1.14.15". - - - - - - - - - - - - A SHA1 checksum. - - - - - - - - - A file checksum, currently only SHA1. - - - - - - - - - diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/CommandLineParser.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/CommandLineParser.java deleted file mode 100644 index 28918dac..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/CommandLineParser.java +++ /dev/null @@ -1,976 +0,0 @@ -/* - * 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.util; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.utils.ILogger; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map.Entry; - -/** - * Parses the command-line and stores flags needed or requested. - *

- * This is a base class. To be useful you want to: - *

    - *
  • override it. - *
  • pass an action array to the constructor. - *
  • define flags for your actions. - *
- *

- * To use, call {@link #parseArgs(String[])} and then - * call {@link #getValue(String, String, String)}. - */ -public class CommandLineParser { - - /* - * Steps needed to add a new action: - * - Each action is defined as a "verb object" followed by parameters. - * - Either reuse a VERB_ constant or define a new one. - * - Either reuse an OBJECT_ constant or define a new one. - * - Add a new entry to mAction with a one-line help summary. - * - In the constructor, add a define() call for each parameter (either mandatory - * or optional) for the given action. - */ - - /** Internal verb name for internally hidden flags. */ - public static final String GLOBAL_FLAG_VERB = "@@internal@@"; //$NON-NLS-1$ - - /** String to use when the verb doesn't need any object. */ - public static final String NO_VERB_OBJECT = ""; //$NON-NLS-1$ - - /** The global help flag. */ - public static final String KEY_HELP = "help"; - /** The global verbose flag. */ - public static final String KEY_VERBOSE = "verbose"; - /** The global silent flag. */ - public static final String KEY_SILENT = "silent"; - - /** Verb requested by the user. Null if none specified, which will be an error. */ - private String mVerbRequested; - /** Direct object requested by the user. Can be null. */ - private String mDirectObjectRequested; - - /** - * Action definitions. - *

- * This list serves two purposes: first it is used to know which verb/object - * actions are acceptable on the command-line; second it provides a summary - * for each action that is printed in the help. - *

- * Each entry is a string array with: - *

    - *
  • the verb. - *
  • a direct object (use {@link #NO_VERB_OBJECT} if there's no object). - *
  • a description. - *
  • an alternate form for the object (e.g. plural). - *
- */ - private final String[][] mActions; - - private static final int ACTION_VERB_INDEX = 0; - private static final int ACTION_OBJECT_INDEX = 1; - private static final int ACTION_DESC_INDEX = 2; - private static final int ACTION_ALT_OBJECT_INDEX = 3; - - /** - * The map of all defined arguments. - *

- * The key is a string "verb/directObject/longName". - */ - private final HashMap mArguments = new HashMap(); - /** Logger */ - private final ILogger mLog; - - /** - * Constructs a new command-line processor. - * - * @param logger An SDK logger object. Must not be null. - * @param actions The list of actions recognized on the command-line. - * See the javadoc of {@link #mActions} for more details. - * - * @see #mActions - */ - public CommandLineParser(ILogger logger, String[][] actions) { - mLog = logger; - mActions = actions; - - /* - * usage should fit in 80 columns, including the space to print the options: - * " -v --verbose 7890123456789012345678901234567890123456789012345678901234567890" - */ - - define(Mode.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "v", KEY_VERBOSE, - "Verbose mode, shows errors, warnings and all messages.", - false); - define(Mode.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "s", KEY_SILENT, - "Silent mode, shows errors only.", - false); - define(Mode.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "h", KEY_HELP, - "Help on a specific command.", - false); - } - - /** - * Indicates if this command-line can work when no verb is specified. - * The default is false, which generates an error when no verb/object is specified. - * Derived implementations can set this to true if they can deal with a lack - * of verb/action. - */ - public boolean acceptLackOfVerb() { - return false; - } - - - //------------------ - // Helpers to get flags values - - /** Helper that returns true if --verbose was requested. */ - public boolean isVerbose() { - return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_VERBOSE)).booleanValue(); - } - - /** Helper that returns true if --silent was requested. */ - public boolean isSilent() { - return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_SILENT)).booleanValue(); - } - - /** Helper that returns true if --help was requested. */ - public boolean isHelpRequested() { - return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_HELP)).booleanValue(); - } - - /** Returns the verb name from the command-line. Can be null. */ - public String getVerb() { - return mVerbRequested; - } - - /** Returns the direct object name from the command-line. Can be null. */ - public String getDirectObject() { - return mDirectObjectRequested; - } - - //------------------ - - /** - * Raw access to parsed parameter values. - *

- * The default is to scan all parameters. Parameters that have been explicitly set on the - * command line are returned first. Otherwise one with a non-null value is returned. - *

- * Both a verb and a direct object filter can be specified. When they are non-null they limit - * the scope of the search. - *

- * If nothing has been found, return the last default value seen matching the filter. - * - * @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}. If null, all possible - * verbs that match the direct object condition will be examined and the first - * value set will be used. - * @param directObject The direct object name, including {@link #NO_VERB_OBJECT}. If null, - * all possible direct objects that match the verb condition will be examined and - * the first value set will be used. - * @param longFlagName The long flag name for the given action. Mandatory. Cannot be null. - * @return The current value object stored in the parameter, which depends on the argument mode. - */ - public Object getValue(String verb, String directObject, String longFlagName) { - - if (verb != null && directObject != null) { - String key = verb + '/' + directObject + '/' + longFlagName; - Arg arg = mArguments.get(key); - return arg.getCurrentValue(); - } - - Object lastDefault = null; - for (Arg arg : mArguments.values()) { - if (arg.getLongArg().equals(longFlagName)) { - if (verb == null || arg.getVerb().equals(verb)) { - if (directObject == null || arg.getDirectObject().equals(directObject)) { - if (arg.isInCommandLine()) { - return arg.getCurrentValue(); - } - if (arg.getCurrentValue() != null) { - lastDefault = arg.getCurrentValue(); - } - } - } - } - } - - return lastDefault; - } - - /** - * Internal setter for raw parameter value. - * @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}. - * @param directObject The direct object name, including {@link #NO_VERB_OBJECT}. - * @param longFlagName The long flag name for the given action. - * @param value The new current value object stored in the parameter, which depends on the - * argument mode. - */ - protected void setValue(String verb, String directObject, String longFlagName, Object value) { - String key = verb + '/' + directObject + '/' + longFlagName; - Arg arg = mArguments.get(key); - arg.setCurrentValue(value); - } - - /** - * Parses the command-line arguments. - *

- * This method will exit and not return if a parsing error arise. - * - * @param args The arguments typically received by a main method. - */ - public void parseArgs(String[] args) { - String errorMsg = null; - String verb = null; - String directObject = null; - - try { - int n = args.length; - for (int i = 0; i < n; i++) { - Arg arg = null; - String a = args[i]; - if (a.startsWith("--")) { //$NON-NLS-1$ - arg = findLongArg(verb, directObject, a.substring(2)); - } else if (a.startsWith("-")) { //$NON-NLS-1$ - arg = findShortArg(verb, directObject, a.substring(1)); - } - - // No matching argument name found - if (arg == null) { - // Does it looks like a dashed parameter? - if (a.startsWith("-")) { //$NON-NLS-1$ - if (verb == null || directObject == null) { - // It looks like a dashed parameter and we don't have a a verb/object - // set yet, the parameter was just given too early. - - errorMsg = String.format( - "Flag '%1$s' is not a valid global flag. Did you mean to specify it after the verb/object name?", - a); - return; - } else { - // It looks like a dashed parameter but it is unknown by this - // verb-object combination - - errorMsg = String.format( - "Flag '%1$s' is not valid for '%2$s %3$s'.", - a, verb, directObject); - return; - } - } - - if (verb == null) { - // Fill verb first. Find it. - for (String[] actionDesc : mActions) { - if (actionDesc[ACTION_VERB_INDEX].equals(a)) { - verb = a; - break; - } - } - - // Error if it was not a valid verb - if (verb == null) { - errorMsg = String.format( - "Expected verb after global parameters but found '%1$s' instead.", - a); - return; - } - - } else if (directObject == null) { - // Then fill the direct object. Find it. - for (String[] actionDesc : mActions) { - if (actionDesc[ACTION_VERB_INDEX].equals(verb)) { - if (actionDesc[ACTION_OBJECT_INDEX].equals(a)) { - directObject = a; - break; - } else if (actionDesc.length > ACTION_ALT_OBJECT_INDEX && - actionDesc[ACTION_ALT_OBJECT_INDEX].equals(a)) { - // if the alternate form exist and is used, we internally - // only memorize the default direct object form. - directObject = actionDesc[ACTION_OBJECT_INDEX]; - break; - } - } - } - - // Error if it was not a valid object for that verb - if (directObject == null) { - errorMsg = String.format( - "Expected verb after global parameters but found '%1$s' instead.", - a); - return; - - } - } else { - // The argument is not a dashed parameter and we already - // have a verb/object. Must be some extra unknown argument. - errorMsg = String.format( - "Argument '%1$s' is not recognized.", - a); - } - } else if (arg != null) { - // This argument was present on the command line - arg.setInCommandLine(true); - - // Process keyword - Object error = null; - if (arg.getMode().needsExtra()) { - if (i+1 >= n) { - errorMsg = String.format("Missing argument for flag %1$s.", a); - return; - } - - while (i+1 < n) { - String b = args[i+1]; - - if (arg.getMode() != Mode.STRING_ARRAY) { - // We never accept something that looks like a valid argument - // unless we see -- first - Arg dummyArg = null; - if (b.startsWith("--")) { //$NON-NLS-1$ - dummyArg = findLongArg(verb, directObject, b.substring(2)); - } else if (b.startsWith("-")) { //$NON-NLS-1$ - dummyArg = findShortArg(verb, directObject, b.substring(1)); - } - if (dummyArg != null) { - errorMsg = String.format( - "Oops, it looks like you didn't provide an argument for '%1$s'.\n'%2$s' was found instead.", - a, b); - return; - } - } - - error = arg.getMode().process(arg, b); - if (error == Accept.CONTINUE) { - i++; - } else if (error == Accept.ACCEPT_AND_STOP) { - i++; - break; - } else if (error == Accept.REJECT_AND_STOP) { - break; - } else if (error instanceof String) { - // We stop because of an error - break; - } - } - } else { - error = arg.getMode().process(arg, null); - - if (isHelpRequested()) { - // The --help flag was requested. We'll continue the usual processing - // so that we can find the optional verb/object words. Those will be - // used to print specific help. - // Setting a non-null error message triggers printing the help, however - // there is no specific error to print. - errorMsg = ""; //$NON-NLS-1$ - } - } - - if (error instanceof String) { - errorMsg = String.format("Invalid usage for flag %1$s: %2$s.", a, error); - return; - } - } - } - - if (errorMsg == null) { - if (verb == null && !acceptLackOfVerb()) { - errorMsg = "Missing verb name."; - } else if (verb != null) { - if (directObject == null) { - // Make sure this verb has an optional direct object - for (String[] actionDesc : mActions) { - if (actionDesc[ACTION_VERB_INDEX].equals(verb) && - actionDesc[ACTION_OBJECT_INDEX].equals(NO_VERB_OBJECT)) { - directObject = NO_VERB_OBJECT; - break; - } - } - - if (directObject == null) { - errorMsg = String.format("Missing object name for verb '%1$s'.", verb); - return; - } - } - - // Validate that all mandatory arguments are non-null for this action - String missing = null; - boolean plural = false; - for (Entry entry : mArguments.entrySet()) { - Arg arg = entry.getValue(); - if (arg.getVerb().equals(verb) && - arg.getDirectObject().equals(directObject)) { - if (arg.isMandatory() && arg.getCurrentValue() == null) { - if (missing == null) { - missing = "--" + arg.getLongArg(); //$NON-NLS-1$ - } else { - missing += ", --" + arg.getLongArg(); //$NON-NLS-1$ - plural = true; - } - } - } - } - - if (missing != null) { - errorMsg = String.format( - "The %1$s %2$s must be defined for action '%3$s %4$s'", - plural ? "parameters" : "parameter", - missing, - verb, - directObject); - } - - mVerbRequested = verb; - mDirectObjectRequested = directObject; - } - } - } finally { - if (errorMsg != null) { - printHelpAndExitForAction(verb, directObject, errorMsg); - } - } - } - - /** - * Finds an {@link Arg} given an action name and a long flag name. - * @return The {@link Arg} found or null. - */ - protected Arg findLongArg(String verb, String directObject, String longName) { - if (verb == null) { - verb = GLOBAL_FLAG_VERB; - } - if (directObject == null) { - directObject = NO_VERB_OBJECT; - } - String key = verb + '/' + directObject + '/' + longName; //$NON-NLS-1$ - return mArguments.get(key); - } - - /** - * Finds an {@link Arg} given an action name and a short flag name. - * @return The {@link Arg} found or null. - */ - protected Arg findShortArg(String verb, String directObject, String shortName) { - if (verb == null) { - verb = GLOBAL_FLAG_VERB; - } - if (directObject == null) { - directObject = NO_VERB_OBJECT; - } - - for (Entry entry : mArguments.entrySet()) { - Arg arg = entry.getValue(); - if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) { - if (shortName.equals(arg.getShortArg())) { - return arg; - } - } - } - - return null; - } - - /** - * Prints the help/usage and exits. - * - * @param errorFormat Optional error message to print prior to usage using String.format - * @param args Arguments for String.format - */ - public void printHelpAndExit(String errorFormat, Object... args) { - printHelpAndExitForAction(null /*verb*/, null /*directObject*/, errorFormat, args); - } - - /** - * Prints the help/usage and exits. - * - * @param verb If null, displays help for all verbs. If not null, display help only - * for that specific verb. In all cases also displays general usage and action list. - * @param directObject If null, displays help for all verb objects. - * If not null, displays help only for that specific action - * In all cases also display general usage and action list. - * @param errorFormat Optional error message to print prior to usage using String.format - * @param args Arguments for String.format - */ - public void printHelpAndExitForAction(String verb, String directObject, - String errorFormat, Object... args) { - if (errorFormat != null && !errorFormat.isEmpty()) { - stderr(errorFormat, args); - } - - /* - * usage should fit in 80 columns - * 12345678901234567890123456789012345678901234567890123456789012345678901234567890 - */ - stdout("\n" + - "Usage:\n" + - " android [global options] %s [action options]\n" + - "\n" + - "Global options:", - verb == null ? "action" : - verb + (directObject == null ? "" : " " + directObject)); //$NON-NLS-1$ - listOptions(GLOBAL_FLAG_VERB, NO_VERB_OBJECT); - - if (verb == null || directObject == null) { - stdout("\nValid actions are composed of a verb and an optional direct object:"); - for (String[] action : mActions) { - if (verb == null || verb.equals(action[ACTION_VERB_INDEX])) { - stdout("- %1$6s %2$-13s: %3$s", - action[ACTION_VERB_INDEX], - action[ACTION_OBJECT_INDEX], - action[ACTION_DESC_INDEX]); - } - } - } - - // Only print details if a verb/object is requested - if (verb != null) { - for (String[] action : mActions) { - if (verb == null || verb.equals(action[ACTION_VERB_INDEX])) { - if (directObject == null || directObject.equals(action[ACTION_OBJECT_INDEX])) { - stdout("\nAction \"%1$s %2$s\":", - action[ACTION_VERB_INDEX], - action[ACTION_OBJECT_INDEX]); - stdout(" %1$s", action[ACTION_DESC_INDEX]); - stdout("Options:"); - listOptions(action[ACTION_VERB_INDEX], action[ACTION_OBJECT_INDEX]); - } - } - } - } - - exit(); - } - - /** - * Internal helper to print all the option flags for a given action name. - */ - protected void listOptions(String verb, String directObject) { - int numOptions = 0; - int longArgLen = 8; - - for (Entry entry : mArguments.entrySet()) { - Arg arg = entry.getValue(); - if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) { - int n = arg.getLongArg().length(); - if (n > longArgLen) { - longArgLen = n; - } - } - } - - for (Entry entry : mArguments.entrySet()) { - Arg arg = entry.getValue(); - if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) { - - String value = ""; //$NON-NLS-1$ - String required = ""; //$NON-NLS-1$ - if (arg.isMandatory()) { - required = " [required]"; - - } else { - if (arg.getDefaultValue() instanceof String[]) { - for (String v : (String[]) arg.getDefaultValue()) { - if (!value.isEmpty()) { - value += ", "; - } - value += v; - } - } else if (arg.getDefaultValue() != null) { - Object v = arg.getDefaultValue(); - if (arg.getMode() != Mode.BOOLEAN || v.equals(Boolean.TRUE)) { - value = v.toString(); - } - } - if (!value.isEmpty()) { - value = " [Default: " + value + "]"; - } - } - - // Java doesn't support * for printf variable width, so we'll insert the long arg - // width "manually" in the printf format string. - String longArgWidth = Integer.toString(longArgLen + 2); - - // Print a line in the form " -1_letter_arg --long_arg description" - // where either the 1-letter arg or the long arg are optional. - String output = String.format( - " %1$-2s %2$-" + longArgWidth + "s: %3$s%4$s%5$s", //$NON-NLS-1$ //$NON-NLS-2$ - !arg.getShortArg().isEmpty() ? - "-" + arg.getShortArg() : //$NON-NLS-1$ - "", //$NON-NLS-1$ - !arg.getLongArg().isEmpty() ? - "--" + arg.getLongArg() : //$NON-NLS-1$ - "", //$NON-NLS-1$ - arg.getDescription(), - value, - required); - stdout(output); - numOptions++; - } - } - - if (numOptions == 0) { - stdout(" No options"); - } - } - - //---- - - protected enum Accept { - CONTINUE, - ACCEPT_AND_STOP, - REJECT_AND_STOP, - } - - /** - * The mode of an argument specifies the type of variable it represents, - * whether an extra parameter is required after the flag and how to parse it. - */ - protected enum Mode { - /** Argument value is a Boolean. Default value is a Boolean. */ - BOOLEAN { - @Override - public boolean needsExtra() { - return false; - } - @Override - public Object process(Arg arg, String extra) { - // Toggle the current value - arg.setCurrentValue(! ((Boolean) arg.getCurrentValue()).booleanValue()); - return Accept.ACCEPT_AND_STOP; - } - }, - - /** Argument value is an Integer. Default value is an Integer. */ - INTEGER { - @Override - public boolean needsExtra() { - return true; - } - @Override - public Object process(Arg arg, String extra) { - try { - arg.setCurrentValue(Integer.parseInt(extra)); - return null; - } catch (NumberFormatException e) { - return String.format("Failed to parse '%1$s' as an integer: %2$s", extra, - e.getMessage()); - } - } - }, - - /** Argument value is a String. Default value is a String[]. */ - ENUM { - @Override - public boolean needsExtra() { - return true; - } - @Override - public Object process(Arg arg, String extra) { - StringBuilder desc = new StringBuilder(); - String[] values = (String[]) arg.getDefaultValue(); - for (String value : values) { - if (value.equals(extra)) { - arg.setCurrentValue(extra); - return Accept.ACCEPT_AND_STOP; - } - - if (desc.length() != 0) { - desc.append(", "); - } - desc.append(value); - } - - return String.format("'%1$s' is not one of %2$s", extra, desc.toString()); - } - }, - - /** Argument value is a String. Default value is a null. */ - STRING { - @Override - public boolean needsExtra() { - return true; - } - @Override - public Object process(Arg arg, String extra) { - arg.setCurrentValue(extra); - return Accept.ACCEPT_AND_STOP; - } - }, - - /** Argument value is a {@link List}<String>. Default value is an empty list. */ - STRING_ARRAY { - @Override - public boolean needsExtra() { - return true; - } - @Override - public Object process(Arg arg, String extra) { - // For simplification, a string array doesn't accept something that - // starts with a dash unless a pure -- was seen before. - if (extra != null) { - Object v = arg.getCurrentValue(); - if (v == null) { - ArrayList a = new ArrayList(); - arg.setCurrentValue(a); - v = a; - } - if (v instanceof List) { - @SuppressWarnings("unchecked") List a = (List) v; - - if (extra.equals("--") || - !extra.startsWith("-") || - (extra.startsWith("-") && a.contains("--"))) { - a.add(extra); - return Accept.CONTINUE; - } else if (a.isEmpty()) { - return "No values provided"; - } - } - } - return Accept.REJECT_AND_STOP; - } - }; - - /** - * Returns true if this mode requires an extra parameter. - */ - public abstract boolean needsExtra(); - - /** - * Processes the flag for this argument. - * - * @param arg The argument being processed. - * @param extra The extra parameter. Null if {@link #needsExtra()} returned false. - * @return {@link Accept#CONTINUE} if this argument can use multiple values and - * wishes to receive more. - * Or {@link Accept#ACCEPT_AND_STOP} if this was the last value accepted by the argument. - * Or {@link Accept#REJECT_AND_STOP} if this was value was reject and the argument - * stops accepting new values with no error. - * Or a string in case of error. - * Never returns null. - */ - public abstract Object process(Arg arg, String extra); - } - - /** - * An argument accepted by the command-line, also called "a flag". - * Arguments must have a short version (one letter), a long version name and a description. - * They can have a default value, or it can be null. - * Depending on the {@link Mode}, the default value can be a Boolean, an Integer, a String - * or a String array (in which case the first item is the current by default.) - */ - protected static class Arg { - /** Verb for that argument. Never null. */ - private final String mVerb; - /** Direct Object for that argument. Never null, but can be empty string. */ - private final String mDirectObject; - /** The 1-letter short name of the argument, e.g. -v. */ - private final String mShortName; - /** The long name of the argument, e.g. --verbose. */ - private final String mLongName; - /** A description. Never null. */ - private final String mDescription; - /** A default value. Can be null. */ - private final Object mDefaultValue; - /** The argument mode (type + process method). Never null. */ - private final Mode mMode; - /** True if this argument is mandatory for this verb/directobject. */ - private final boolean mMandatory; - /** Current value. Initially set to the default value. */ - private Object mCurrentValue; - /** True if the argument has been used on the command line. */ - private boolean mInCommandLine; - - /** - * Creates a new argument flag description. - * - * @param mode The {@link Mode} for the argument. - * @param mandatory True if this argument is mandatory for this action. - * @param verb The verb name. Never null. Can be {@link CommandLineParser#GLOBAL_FLAG_VERB}. - * @param directObject The action name. Can be {@link CommandLineParser#NO_VERB_OBJECT}. - * @param shortName The one-letter short argument name. Can be empty but not null. - * @param longName The long argument name. Can be empty but not null. - * @param description The description. Cannot be null. - * @param defaultValue The default value (or values), which depends on the selected - * {@link Mode}. Can be null. - */ - public Arg(Mode mode, - boolean mandatory, - @NonNull String verb, - @NonNull String directObject, - @NonNull String shortName, - @NonNull String longName, - @NonNull String description, - @Nullable Object defaultValue) { - mMode = mode; - mMandatory = mandatory; - mVerb = verb; - mDirectObject = directObject; - mShortName = shortName; - mLongName = longName; - mDescription = description; - mDefaultValue = defaultValue; - mInCommandLine = false; - if (defaultValue instanceof String[]) { - mCurrentValue = ((String[])defaultValue)[0]; - } else { - mCurrentValue = mDefaultValue; - } - } - - /** Return true if this argument is mandatory for this verb/directobject. */ - public boolean isMandatory() { - return mMandatory; - } - - /** Returns the 1-letter short name of the argument, e.g. -v. */ - public String getShortArg() { - return mShortName; - } - - /** Returns the long name of the argument, e.g. --verbose. */ - public String getLongArg() { - return mLongName; - } - - /** Returns the description. Never null. */ - public String getDescription() { - return mDescription; - } - - /** Returns the verb for that argument. Never null. */ - public String getVerb() { - return mVerb; - } - - /** Returns the direct Object for that argument. Never null, but can be empty string. */ - public String getDirectObject() { - return mDirectObject; - } - - /** Returns the default value. Can be null. */ - public Object getDefaultValue() { - return mDefaultValue; - } - - /** Returns the current value. Initially set to the default value. Can be null. */ - public Object getCurrentValue() { - return mCurrentValue; - } - - /** Sets the current value. Can be null. */ - public void setCurrentValue(Object currentValue) { - mCurrentValue = currentValue; - } - - /** Returns the argument mode (type + process method). Never null. */ - public Mode getMode() { - return mMode; - } - - /** Returns true if the argument has been used on the command line. */ - public boolean isInCommandLine() { - return mInCommandLine; - } - - /** Sets if the argument has been used on the command line. */ - public void setInCommandLine(boolean inCommandLine) { - mInCommandLine = inCommandLine; - } - } - - /** - * Internal helper to define a new argument for a give action. - * - * @param mode The {@link Mode} for the argument. - * @param mandatory The argument is required (never if {@link Mode#BOOLEAN}) - * @param verb The verb name. Never null. Can be {@link CommandLineParser#GLOBAL_FLAG_VERB}. - * @param directObject The action name. Can be {@link CommandLineParser#NO_VERB_OBJECT}. - * @param shortName The one-letter short argument name. Can be empty but not null. - * @param longName The long argument name. Can be empty but not null. - * @param description The description. Cannot be null. - * @param defaultValue The default value (or values), which depends on the selected - * {@link Mode}. - */ - protected void define(Mode mode, - boolean mandatory, - @NonNull String verb, - @NonNull String directObject, - @NonNull String shortName, - @NonNull String longName, - @NonNull String description, - @Nullable Object defaultValue) { - assert verb != null; - assert(!(mandatory && mode == Mode.BOOLEAN)); // a boolean mode cannot be mandatory - - // We should always have at least a short or long name, ideally both but never none. - assert shortName != null; - assert longName != null; - assert !shortName.isEmpty() || !longName.isEmpty(); - - if (directObject == null) { - directObject = NO_VERB_OBJECT; - } - - String key = verb + '/' + directObject + '/' + longName; - mArguments.put(key, new Arg(mode, mandatory, - verb, directObject, shortName, longName, description, defaultValue)); - } - - /** - * Exits in case of error. - * This is protected so that it can be overridden in unit tests. - */ - protected void exit() { - System.exit(1); - } - - /** - * Prints a line to stdout. - * This is protected so that it can be overridden in unit tests. - * - * @param format The string to be formatted. Cannot be null. - * @param args Format arguments. - */ - protected void stdout(String format, Object...args) { - String output = String.format(format, args); - output = LineUtil.reflowLine(output); - mLog.info("%s\n", output); //$NON-NLS-1$ - } - - /** - * Prints a line to stderr. - * This is protected so that it can be overridden in unit tests. - * - * @param format The string to be formatted. Cannot be null. - * @param args Format arguments. - */ - protected void stderr(String format, Object...args) { - mLog.error(null, format, args); - } - - /** - * Returns the logger object. - * @return the logger object. - */ - protected ILogger getLog() { - return mLog; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/FormatUtils.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/FormatUtils.java deleted file mode 100644 index 0ff5e693..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/FormatUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 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.util; - -import com.android.annotations.NonNull; - -/** - * Helper methods to do some format conversions. - */ -public abstract class FormatUtils { - - /** - * Converts a byte size to a human readable string, - * for example "3 MiB", "1020 Bytes" or "1.2 GiB". - * - * @param size The byte size to convert. - * @return A new non-null string, with the size expressed in either Bytes - * or KiB or MiB or GiB. - */ - @NonNull - public static String byteSizeToString(long size) { - String sizeStr; - - if (size < 1024) { - sizeStr = String.format("%d Bytes", size); - } else if (size < 1024 * 1024) { - sizeStr = String.format("%d KiB", Math.round(size / 1024.0)); - } else if (size < 1024 * 1024 * 1024) { - sizeStr = String.format("%.1f MiB", - Math.round(10.0 * size / (1024 * 1024.0))/ 10.0); - } else { - sizeStr = String.format("%.1f GiB", - Math.round(10.0 * size / (1024 * 1024 * 1024.0))/ 10.0); - } - - return sizeStr; - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/LineUtil.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/LineUtil.java deleted file mode 100644 index c42bd0dd..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/util/LineUtil.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2011 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.util; - - -public abstract class LineUtil { - - /** - * Reformats a line so that it fits in 78 characters max. - *

- * When wrapping the second line and following, prefix the string with a number of - * spaces. This will use the first colon (:) to determine the prefix size - * or use 4 as a minimum if there are no colons in the string. - * - * @param line The line to reflow. Must be non-null. - * @return A new line to print as-is, that contains \n as needed. - */ - public static String reflowLine(String line) { - final int maxLen = 78; - - // Most of time the line will fit in the given length and this will be a no-op - int n = line.length(); - int cr = line.indexOf('\n'); - if (n <= maxLen && (cr == -1 || cr == n - 1)) { - return line; - } - - int prefixSize = line.indexOf(':') + 1; - // If there' some spacing after the colon, use the same when wrapping - if (prefixSize > 0 && prefixSize < maxLen) { - while(prefixSize < n && line.charAt(prefixSize) == ' ') { - prefixSize++; - } - } else { - prefixSize = 4; - } - String prefix = String.format( - "%-" + Integer.toString(prefixSize) + "s", //$NON-NLS-1$ //$NON-NLS-2$ - " "); //$NON-NLS-1$ - - StringBuilder output = new StringBuilder(n + prefixSize); - - while (n > 0) { - cr = line.indexOf('\n'); - if (n <= maxLen && (cr == -1 || cr == n - 1)) { - output.append(line); - break; - } - - // Line is longer than the max length, find the first character before and after - // the whitespace where we want to break the line. - int posNext = maxLen; - if (cr != -1 && cr != n - 1 && cr <= posNext) { - posNext = cr + 1; - while (posNext < n && line.charAt(posNext) == '\n') { - posNext++; - } - } - while (posNext < n && line.charAt(posNext) == ' ') { - posNext++; - } - while (posNext > 0) { - char c = line.charAt(posNext - 1); - if (c != ' ' && c != '\n') { - posNext--; - } else { - break; - } - } - - if (posNext == 0 || (posNext >= n && maxLen < n)) { - // We found no whitespace separator. This should generally not occur. - posNext = maxLen; - } - int posPrev = posNext; - while (posPrev > 0) { - char c = line.charAt(posPrev - 1); - if (c == ' ' || c == '\n') { - posPrev--; - } else { - break; - } - } - - output.append(line.substring(0, posPrev)).append('\n'); - line = prefix + line.substring(posNext); - n = line.length(); - } - - return output.toString(); - } - - /** - * Formats the string using {@link String#format(String, Object...)} - * and then returns the result of {@link #reflowLine(String)}. - * - * @param format The string format. - * @param params The parameters for the string format. - * @return The result of {@link #reflowLine(String)} on the formatted string. - */ - public static String reformatLine(String format, Object...params) { - return reflowLine(String.format(format, params)); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/AboutDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/AboutDialog.java index 9220305a..f32d6437 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/AboutDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/AboutDialog.java @@ -17,31 +17,33 @@ package com.android.sdkuilib.internal.repository; -import com.android.SdkConstants; -import com.android.sdklib.io.LegacyFileOp; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; +import com.android.SdkConstants; +import com.android.repository.api.LocalPackage; +import com.android.repository.io.FileOp; +import com.android.repository.io.FileOpUtils; +import com.android.sdklib.repository.PkgProps; +import com.android.sdkuilib.ui.GridDataBuilder; +import com.android.sdkuilib.ui.GridLayoutBuilder; public class AboutDialog extends UpdaterBaseDialog { - public AboutDialog(Shell parentShell, SwtUpdaterData swtUpdaterData) { - super(parentShell, swtUpdaterData, "About" /*title*/); - assert swtUpdaterData != null; + private static final String COPYRIGHT = "Copyright (C) 2009-2017"; + + public AboutDialog(Shell parentShell, SdkContext sdkContext) { + super(parentShell, sdkContext, "About" /*title*/); } @Override @@ -54,23 +56,21 @@ protected void createContents() { GridLayoutBuilder.create(shell).columns(3); Label logo = new Label(shell, SWT.NONE); - ImageFactory imgf = getSwtUpdaterData() == null ? null - : getSwtUpdaterData().getImageFactory(); + ImageFactory imgf = mSdkContext.getSdkHelper().getImageFactory(); Image image = imgf == null ? null : imgf.getImageByName("sdkman_logo_128.png"); if (image != null) logo.setImage(image); Label label = new Label(shell, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab().hSpan(2);; + GridDataBuilder.create(label).hFill().hGrab().hSpan(2); + String version = getVersion(); + if (!version.isEmpty()) + version = String.format("Revision %1$s", version); label.setText(String.format( "Android SDK Manager.\n" + - "Revision %1$s\n" + - "Add-on XML Schema #%2$d\n" + - "Repository XML Schema #%3$d\n" + - // TODO: update with new year date (search this to find other occurrences to update) - "Copyright (C) 2009-2012 The Android Open Source Project.", - getRevision(), - SdkAddonConstants.NS_LATEST_VERSION, - SdkRepoConstants.NS_LATEST_VERSION)); + "%1$s\n" + + "%2$s The Android Open Source Project.", + version, + COPYRIGHT)); Label filler = new Label(shell, SWT.NONE); GridDataBuilder.create(filler).fill().grab().hSpan(2); @@ -90,32 +90,30 @@ protected void checkSubclass() { // End of hiding from SWT Designer //$hide<<$ - private String getRevision() { + private String getVersion() { + LocalPackage platformPackage = mSdkContext.getHandler().getLatestLocalPackageForPrefix(SdkConstants.FD_TOOLS, false, mSdkContext.getProgressIndicator()); + if (platformPackage != null) + return platformPackage.getVersion().toShortString(); + return getToolsVersion(); + } + + private String getToolsVersion() { Properties p = new Properties(); - try{ - File sourceProp = LegacyFileOp.append(getSwtUpdaterData().getOsSdkRoot(), - SdkConstants.FD_TOOLS, - SdkConstants.FN_SOURCE_PROP); - FileInputStream fis = null; - try { - fis = new FileInputStream(sourceProp); - p.load(fis); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException ignore) { - } - } - } - - String revision = p.getProperty(PkgProps.PKG_REVISION); - if (revision != null) { - return revision; + File suffix = new File(SdkConstants.FD_TOOLS, SdkConstants.FN_SOURCE_PROP); + FileOp fileOp = FileOpUtils.create(); + InputStream fis = null; + try { + fis = fileOp.newFileInputStream(new File(mSdkContext.getLocation().toString(), suffix.toString())); + p.load(fis); + } catch (IOException ignore) { + } finally { + if (fis != null) + try { + fis.close(); + } catch (IOException ignore) { } - } catch (IOException e) { } - - return "?"; + return p.getProperty(PkgProps.PKG_REVISION, ""); } + } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java index 88a9ac13..2e442f8b 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java @@ -16,7 +16,7 @@ package com.android.sdkuilib.internal.repository; -import com.android.sdklib.repository.ISdkChangeListener; +import com.android.sdkuilib.repository.ISdkChangeListener; /** * Interface for the actual implementation of the Update Window. diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISwtUpdaterData.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISwtUpdaterData.java deleted file mode 100644 index 916423e0..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ISwtUpdaterData.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 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.sdkuilib.internal.repository; - -import com.android.sdklib.internal.repository.updater.IUpdaterData; -import com.android.sdklib.internal.repository.updater.UpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; - -import org.eclipse.swt.widgets.Shell; - - -/** - * Interface used to retrieve some parameters from an {@link UpdaterData} instance. - * Useful mostly for unit tests purposes. - */ -interface ISwtUpdaterData extends IUpdaterData { - - public abstract ImageFactory getImageFactory(); - - public abstract Shell getWindowShell(); - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITask.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITask.java similarity index 80% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITask.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITask.java index 58e76f9c..b97bd1b3 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITask.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITask.java @@ -1,31 +1,25 @@ -/* - * Copyright (C) 2009 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.internal.repository; - - -/** - * A task that executes and can update a monitor to display its status. - * The task will generally be run in a separate thread. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface ITask { - void run(ITaskMonitor monitor); -} +/* + * Copyright (C) 2009 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.sdkuilib.internal.repository; + +/** + * A task that executes and can update a monitor to display its status. + * The task will generally be run in a separate thread. + */ +public interface ITask { + void run(ITaskMonitor monitor); +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskFactory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskFactory.java similarity index 92% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskFactory.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskFactory.java index ce7133aa..afe16852 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskFactory.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskFactory.java @@ -1,64 +1,59 @@ -/* - * Copyright (C) 2009 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.internal.repository; - - -/** - * A factory that can start and run new {@link ITask}s. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface ITaskFactory { - - /** - * Starts a new task with a new {@link ITaskMonitor}. - *

- * The task will execute in a thread and runs it own UI loop. - * This means the task can perform UI operations using - * {@code Display#asyncExec(Runnable)}. - *

- * In either case, the method only returns when the task has finished. - * - * @param title The title of the task, displayed in the monitor if any. - * @param task The task to run. - */ - void start(String title, ITask task); - - /** - * Starts a new task contributing to an already existing {@link ITaskMonitor}. - *

- * To use this properly, you should use {@link ITaskMonitor#createSubMonitor(int)} - * and give the sub-monitor to the new task with the number of work units you want - * it to fill. The {@link #start} method will make sure to fill the progress - * when the task is completed, in case the actual task did not. - *

- * When a task is started from within a monitor, it reuses the thread - * from the parent. Otherwise it starts a new thread and runs it own - * UI loop. This means the task can perform UI operations using - * {@code Display#asyncExec(Runnable)}. - *

- * In either case, the method only returns when the task has finished. - * - * @param title The title of the task, displayed in the monitor if any. - * @param parentMonitor The parent monitor. Can be null. - * @param task The task to run and have it display on the monitor. - */ - void start(String title, ITaskMonitor parentMonitor, ITask task); -} +/* + * Copyright (C) 2009 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.sdkuilib.internal.repository; + + +/** + * A factory that can start and run new {@link ITask}s. + */ +public interface ITaskFactory { + + /** + * Starts a new task with a new {@link ITaskMonitor}. + *

+ * The task will execute in a thread and runs it own UI loop. + * This means the task can perform UI operations using + * {@code Display#asyncExec(Runnable)}. + *

+ * In either case, the method only returns when the task has finished. + * + * @param title The title of the task, displayed in the monitor if any. + * @param task The task to run. + */ + void start(String title, ITask task); + + /** + * Starts a new task contributing to an already existing {@link ITaskMonitor}. + *

+ * To use this properly, you should use {@link ITaskMonitor#createSubMonitor(int)} + * and give the sub-monitor to the new task with the number of work units you want + * it to fill. The {@link #start} method will make sure to fill the progress + * when the task is completed, in case the actual task did not. + *

+ * When a task is started from within a monitor, it reuses the thread + * from the parent. Otherwise it starts a new thread and runs it own + * UI loop. This means the task can perform UI operations using + * {@code Display#asyncExec(Runnable)}. + *

+ * In either case, the method only returns when the task has finished. + * + * @param title The title of the task, displayed in the monitor if any. + * @param parentMonitor The parent monitor. Can be null. + * @param task The task to run and have it display on the monitor. + */ + void start(String title, ITaskMonitor parentMonitor, ITask task); +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskMonitor.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskMonitor.java similarity index 90% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskMonitor.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskMonitor.java index 89aac97f..966fc58c 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/ITaskMonitor.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ITaskMonitor.java @@ -1,152 +1,158 @@ -/* - * Copyright (C) 2009 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.internal.repository; - -import com.android.utils.ILogger; - - -/** - * A monitor interface for a {@link ITask}. - *

- * Depending on the task factory that created the task, there might not be any UI - * or it might not implement all the methods, in which case calling them would be - * a no-op but is guaranteed not to crash. - *

- * If the task runs in a non-UI worker thread, the task factory implementation - * will take care of the update the UI in the correct thread. The task itself - * must not have to deal with it. - *

- * A monitor typically has 3 levels of text displayed:
- * - A title may be present on a task dialog, typically when a task - * dialog is created. This is not covered by this monitor interface.
- * - A description displays prominent information on what the task - * is currently doing. This is expected to vary over time, typically changing - * with each sub-monitor, and typically only the last description is visible. - * For example an updater would typically have descriptions such as "downloading", - * "installing" and finally "done". This is set using {@link #setDescription}.
- * - A verbose optional log that can provide more information than the summary - * description and is typically displayed in some kind of scrollable multi-line - * text field so that the user can keep track of what happened. 3 levels are - * provided: error, normal and verbose. An UI may hide the log till an error is - * logged and/or might hide the verbose text unless a flag is checked by the user. - * This is set using {@link #log}, {@link #logError} and {@link #logVerbose}. - *

- * A monitor is also an {@link ILogger} implementation. - * - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public interface ITaskMonitor extends ILogger { - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - void setDescription(String format, Object...args); - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - void log(String format, Object...args); - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - void logError(String format, Object...args); - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - void logVerbose(String format, Object...args); - - /** - * Sets the max value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * This method MUST be invoked once before using {@link #incProgress(int)} or - * {@link #getProgress()} or {@link #createSubMonitor(int)}. Callers are - * discouraged from using more than once -- implementations can either discard - * the next calls or behave incoherently. - */ - void setProgressMax(int max); - - /** - * Returns the max value of the progress bar, as last set by {@link #setProgressMax(int)}. - * Returns 0 if the max has never been set yet. - */ - int getProgressMax(); - - /** - * Increments the current value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * Callers MUST use setProgressMax before using this method. - */ - void incProgress(int delta); - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - * - * Callers MUST use setProgressMax before using this method. - */ - int getProgress(); - - /** - * Returns true if the user requested to cancel the operation. - * It is up to the task thread to pool this and exit as soon - * as possible. - */ - boolean isCancelRequested(); - - /** - * Creates a sub-monitor that will use up to tickCount on the progress bar. - * tickCount must be 1 or more. - */ - ITaskMonitor createSubMonitor(int tickCount); - - /** - * Display a yes/no question dialog box. - * - * Implementations MUST allow this to be called from any thread, e.g. by - * making sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - boolean displayPrompt(final String title, final String message); - - /** - * Launch an interface which asks for user credentials. Implementations - * MUST allow this to be called from any thread, e.g. by making sure the - * dialog is opened synchronously in the UI thread. - * - * @param title The title of the dialog box. - * @param message The message to be displayed as an instruction. - * @return Returns the user provided credentials. Some fields may be blank if the user - * did not provide any input. - If operation is canceled by user the return value must be null. - */ - UserCredentials displayLoginCredentialsPrompt(String title, String message); -} +/* + * Copyright (C) 2009 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.sdkuilib.internal.repository; + +import com.android.utils.ILogger; + + +/** + * A monitor interface for a {@link ITask}. + *

+ * Depending on the task factory that created the task, there might not be any UI + * or it might not implement all the methods, in which case calling them would be + * a no-op but is guaranteed not to crash. + *

+ * If the task runs in a non-UI worker thread, the task factory implementation + * will take care of the update the UI in the correct thread. The task itself + * must not have to deal with it. + *

+ * A monitor typically has 3 levels of text displayed:
+ * - A title may be present on a task dialog, typically when a task + * dialog is created. This is not covered by this monitor interface.
+ * - A description displays prominent information on what the task + * is currently doing. This is expected to vary over time, typically changing + * with each sub-monitor, and typically only the last description is visible. + * For example an updater would typically have descriptions such as "downloading", + * "installing" and finally "done". This is set using {@link #setDescription}.
+ * - A verbose optional log that can provide more information than the summary + * description and is typically displayed in some kind of scrollable multi-line + * text field so that the user can keep track of what happened. 3 levels are + * provided: error, normal and verbose. An UI may hide the log till an error is + * logged and/or might hide the verbose text unless a flag is checked by the user. + * This is set using {@link #log}, {@link #logError} and {@link #logVerbose}. + *

+ * A monitor is also an {@link ILogger} implementation. + */ +public interface ITaskMonitor extends ILogger { + + /** + * Sets the description in the current task dialog. + * This method can be invoked from a non-UI thread. + */ + void setDescription(String format, Object...args); + + /** + * Logs a "normal" information line. + * This method can be invoked from a non-UI thread. + */ + void log(String format, Object...args); + + /** + * Logs an "error" information line. + * This method can be invoked from a non-UI thread. + */ + void logError(String format, Object...args); + + /** + * Logs a "verbose" information line, that is extra details which are typically + * not that useful for the end-user and might be hidden until explicitly shown. + * This method can be invoked from a non-UI thread. + */ + void logVerbose(String format, Object...args); + + /** + * Sets the max value of the progress bar. + * This method can be invoked from a non-UI thread. + * + * This method MUST be invoked once before using {@link #incProgress(int)} or + * {@link #getProgress()} or {@link #createSubMonitor(int)}. Callers are + * discouraged from using more than once -- implementations can either discard + * the next calls or behave incoherently. + */ + void setProgressMax(int max); + + /** + * Returns the max value of the progress bar, as last set by {@link #setProgressMax(int)}. + * Returns 0 if the max has never been set yet. + */ + int getProgressMax(); + + /** + * Increments the current value of the progress bar. + * This method can be invoked from a non-UI thread. + * + * Callers MUST use setProgressMax before using this method. + */ + void incProgress(int delta); + + /** + * Returns the current value of the progress bar, + * between 0 and up to {@link #setProgressMax(int)} - 1. + * + * Callers MUST use setProgressMax before using this method. + */ + int getProgress(); + + /** + * Returns true if the user requested to cancel the operation. + * It is up to the task thread to pool this and exit as soon + * as possible. + */ + boolean isCancelRequested(); + + /** + * Creates a sub-monitor that will use up to tickCount on the progress bar. + * tickCount must be 1 or more. + */ + ITaskMonitor createSubMonitor(int tickCount); + + /** + * Display a yes/no question dialog box. + * + * Implementations MUST allow this to be called from any thread, e.g. by + * making sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + * @return true if YES was clicked. + */ + boolean displayPrompt(final String title, final String message); + + /** + * Display info dialog box. + * + * Implementations MUST allow this to be called from any thread, e.g. by + * making sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + */ + void displayInfo(final String title, final String message); + + /** + * Launch an interface which asks for user credentials. Implementations + * MUST allow this to be called from any thread, e.g. by making sure the + * dialog is opened synchronously in the UI thread. + * + * @param title The title of the dialog box. + * @param message The message to be displayed as an instruction. + * @return Returns the user provided credentials. Some fields may be blank if the user + * did not provide any input. + If operation is canceled by user the return value must be null. + */ + UserCredentials displayLoginCredentialsPrompt(String title, String message); +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/LoadPackagesRequest.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/LoadPackagesRequest.java new file mode 100644 index 00000000..9813cbb5 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/LoadPackagesRequest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository; + +import java.util.List; + +import com.android.repository.api.ProgressRunner; +import com.android.repository.api.RepoManager.RepoLoadedCallback; + +/** + * Packet containing parameters to call RepoManager load() + * + * + *

public abstract void load(long cacheExpirationMs,
+            @Nullable List onLocalComplete,
+            @Nullable List onSuccess,
+            @Nullable List onError,
+            @NonNull ProgressRunner runner,
+            @Nullable Downloader downloader,
+            @Nullable SettingsController settings,
+            boolean sync);
+        
+ * @author Andrew Bowley + * + * 12-11-2017 + */ +public class LoadPackagesRequest { + + private ProgressRunner runner; + private List onLocalComplete; + private List onSuccess; + private List onError; + + /** + * + */ + public LoadPackagesRequest(ProgressRunner runner) { + this.runner = runner; + } + + public List getOnLocalComplete() { + return onLocalComplete; + } + + public void setOnLocalComplete(List onLocalComplete) { + this.onLocalComplete = onLocalComplete; + } + + public List getOnSuccess() { + return onSuccess; + } + + public void setOnSuccess(List onSuccess) { + this.onSuccess = onSuccess; + } + + public List getOnError() { + return onError; + } + + public void setOnError(List onError) { + this.onError = onError; + } + + public ProgressRunner getRunner() { + return runner; + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/MenuBarWrapper.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/MenuBarWrapper.java index feea181f..d7edfd13 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/MenuBarWrapper.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/MenuBarWrapper.java @@ -19,7 +19,6 @@ import com.android.menubar.IMenuBarCallback; import com.android.menubar.MenuBarEnhancer; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; import org.eclipse.swt.widgets.Menu; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageInfo.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageInfo.java new file mode 100644 index 00000000..a06effc3 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageInfo.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009-2017 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.sdkuilib.internal.repository; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.RemotePackage; + +/** + * Represents package that we want to install. + *

+ * A new package is a remote package that needs to be downloaded and then + * installed. It can replace an existing local one. It can also depend on another + * (new or local) package, which means the dependent package needs to be successfully + * installed first. Finally this package can also be a dependency for another one. + *

+ * The accepted and rejected flags are used by {@code SdkUpdaterChooserDialog} to follow + * user choices. The installer should never install something that is not accepted. + *

+ * Note: There is currently no logic to support more than one level of + * dependency, either here or in the {@code SdkUpdaterChooserDialog}, since we currently + * have no need for it. + */ +public class PackageInfo implements Comparable { + + private final RemotePackage mNewPackage; + private LocalPackage mReplaced; + private boolean mAccepted; + private boolean mRejected; + + /** + * Creates a new replacement where the {@code newPackage} will replace the + * currently installed {@code replaced} package. + * When {@code newPackage} is not intended to replace anything (e.g. because + * the user is installing a new package not present on her system yet), then + * {@code replace} shall be null. + * + * @param newPackage A "new package" to be installed. This is always an package + * that comes from a remote site. + */ + public PackageInfo(@NonNull RemotePackage newPackage) { + this(newPackage, null); + } + + public PackageInfo(@NonNull RemotePackage newPackage, @Nullable LocalPackage replaced) { + mNewPackage = newPackage; + mReplaced = replaced; + } + + /** + * Returns the "new archive" to be installed. + * This may be null for missing archives. + */ + public RemotePackage getNewPackage() { + return mNewPackage; + } + + /** + * Returns an optional local archive that the new one will replace. + * Can be null if this archive does not replace anything. + */ + public LocalPackage getReplaced() { + return mReplaced; + } + + /** + * Sets whether this package was accepted (either manually by the user or + * automatically if it doesn't have a license) for installation. + */ + public void setAccepted(boolean accepted) { + mAccepted = accepted; + } + + /** + * Returns whether this package was accepted (either manually by the user or + * automatically if it doesn't have a license) for installation. + */ + public boolean isAccepted() { + return mAccepted; + } + + /** + * Sets whether this package was rejected manually by the user. + * An package can neither accepted nor rejected. + */ + public void setRejected(boolean rejected) { + mRejected = rejected; + } + + /** + * Returns whether this package was rejected manually by the user. + * An package can neither accepted nor rejected. + */ + public boolean isRejected() { + return mRejected; + } + + /** + * PackageInfos are compared using ther "new package" ordering. + * + * @see Package#compareTo(Package) + */ + @Override + public int compareTo(PackageInfo rhs) { + if (mNewPackage != null && rhs != null) { + return mNewPackage.compareTo(rhs.mNewPackage); + } + return 0; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageManager.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageManager.java new file mode 100644 index 00000000..8b4ad535 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/PackageManager.java @@ -0,0 +1,282 @@ +package com.android.sdkuilib.internal.repository; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.andmore.sdktool.SdkContext; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.annotations.VisibleForTesting; +import com.android.annotations.VisibleForTesting.Visibility; +import com.android.repository.api.Downloader; +import com.android.repository.api.Installer; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.PackageOperation; +import com.android.repository.api.ProgressIndicator; +import com.android.repository.api.ProgressRunner; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoManager; +import com.android.repository.api.RepoManager.RepoLoadedCallback; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.RepositoryPackages; +import com.android.repository.io.FileOpUtils; +import com.android.repository.io.impl.FileSystemFileOp; +import com.android.sdklib.repository.installer.SdkInstallerUtil; +import com.android.sdklib.repository.legacy.LegacyDownloader; +import com.google.common.collect.Maps; + +public class PackageManager { + + public interface LocalPackageHandler + { + void onPackageLoaded(LocalPackage localPackage); + } + + public interface RemotePackageHandler + { + void onPackageLoaded(RemotePackage remotePackage); + } + + public interface UpdatablePackageHandler + { + void onPackageLoaded(UpdatablePackage updatablePackage); + } + + /** + * Map from {@code path} (the unique ID of a package) to {@link UpdatablePackage}, including all + * packages installed or available. + */ + private final Map consolidatedPkgs = Maps.newTreeMap(); + private final SdkContext sdkContext; + private final Downloader downloader; + private RepositoryPackages packages; + + public PackageManager(SdkContext sdkContext) + { + this.sdkContext = sdkContext; + downloader = downloaderInstance(); + } + + public Downloader getDownloader() + { + return downloader; + } + + public UpdatablePackage getPackageById(String id) + { + return consolidatedPkgs.get(id); + } + + public boolean loadLocalPackages(LocalPackageHandler handler) + { + sdkContext.getRepoManager().loadSynchronously(0, sdkContext.getProgressIndicator(), downloader, sdkContext.getSettings()); + if (sdkContext.hasError()) + return false; + + for (LocalPackage local : getRepositoryPackages().getLocalPackages().values()) + handler.onPackageLoaded(local); + return true; + } + + public boolean loadRemotePackages(RemotePackageHandler handler) + { + sdkContext.getRepoManager().loadSynchronously(0, sdkContext.getProgressIndicator(), downloader, sdkContext.getSettings()); + if (sdkContext.hasError()) + return false; + + for (RemotePackage remote : getRepositoryPackages().getRemotePackages().values()) + handler.onPackageLoaded(remote); + return true; + } + + public boolean loadUpdatablePackages(UpdatablePackageHandler handler) + { + if (sdkContext.hasError()) + return false; + for (UpdatablePackage updatable : getRepositoryPackages().getUpdatedPkgs()) + handler.onPackageLoaded(updatable); + return true; + } + + public boolean loadConsolidatedPackages(UpdatablePackageHandler handler) + { + if (sdkContext.hasError()) + return false; + consolidatedPkgs.clear(); + consolidatedPkgs.putAll(getRepositoryPackages().getConsolidatedPkgs()); + for (UpdatablePackage updatable : consolidatedPkgs.values()) + handler.onPackageLoaded(updatable); + return true; + } + + public RepositoryPackages getRepositoryPackages() + { + if (packages == null) + { + RepoManager repoManager = sdkContext.getRepoManager(); + repoManager.loadSynchronously(0, sdkContext.getProgressIndicator(), downloader, sdkContext.getSettings()); + packages = repoManager.getPackages(); + } + return packages; + } +/* + public abstract void load(long cacheExpirationMs, + @Nullable List onLocalComplete, + @Nullable List onSuccess, + @Nullable List onError, + @NonNull ProgressRunner runner, + @Nullable Downloader downloader, + @Nullable SettingsController settings, + boolean sync); + */ + + public void requestRepositoryPackages(LoadPackagesRequest loadPackagesRequest) + { + RepoManager repoManager = sdkContext.getRepoManager(); + repoManager.load(0, + loadPackagesRequest.getOnLocalComplete(), + loadPackagesRequest.getOnSuccess(), + loadPackagesRequest.getOnError(), + loadPackagesRequest.getRunner(), + downloader, + sdkContext.getSettings(), + false); + } + + public RepositoryPackages getRepositoryPackages( + @Nullable List onLocalComplete, + @Nullable List onSuccess, + @Nullable List onError, + @NonNull ProgressRunner runner) + { + if (packages == null) + { + RepoManager repoManager = sdkContext.getRepoManager(); + repoManager.load(0, onLocalComplete, onSuccess, onError, runner, downloader, sdkContext.getSettings(), true); + packages = repoManager.getPackages(); + } + return packages; + } + + public void setPackages(RepositoryPackages packages) { + this.packages = packages; + } + + /** + * Install the list of given {@link Package}s. This is invoked by the user selecting some + * packages in the remote page and then clicking "install selected". + * + * @param packages The packages to install. + * @param taskFactory Task factory to show progress during installation + * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. + * @return A list of packages that have been installed. Can be empty but not null. + */ + @VisibleForTesting(visibility=Visibility.PRIVATE) + public int installPackages(final List packages, List acceptedRemotes, ITaskFactory taskFactory, final int flags) { + // List to accumulate all the packages installed. + int[] numInstalled = new int[]{0}; + taskFactory.start("Installing Packages", new ITask() { + @Override + public void run(ITaskMonitor monitor) { + List rejectedRemotes = new ArrayList<>(); + Iterator iterator = packages.iterator(); + while (iterator.hasNext()) { + RemotePackage remote = iterator.next(); + if (!acceptedRemotes.contains(remote)) + rejectedRemotes.add(remote); + } + List remotes = new ArrayList<>(); + remotes.addAll(packages); + if (!rejectedRemotes.isEmpty()) { + String title = "Package licences not accepted"; + StringBuilder builder = new StringBuilder(); + builder.append("The following packages can not be installed since their " + + "licenses or those of the packages they depend on were not accepted:"); + Iterator iterator2 = rejectedRemotes.iterator(); + while(iterator2.hasNext()) + builder.append('\n').append(iterator2.next().getPath()); + if (!acceptedRemotes.isEmpty()) { + builder.append("\n\nContinue installing the remaining packages?"); + if (!monitor.displayPrompt(title, + builder.toString())) + return; + else { + monitor.displayInfo(title, builder.toString()); + return; + } + } + remotes = acceptedRemotes; + } + final int progressPerPackage = 2 * 100; + monitor.setProgressMax(1 + remotes.size() * progressPerPackage); + monitor.setDescription("Preparing to install packages"); + for (RemotePackage remotePackage : remotes) { + int nextProgress = monitor.getProgress() + progressPerPackage; + Installer installer = SdkInstallerUtil.findBestInstallerFactory(remotePackage, sdkContext.getHandler()) + .createInstaller(remotePackage, sdkContext.getRepoManager(), downloader, sdkContext.getFileOp()); + if (applyPackageOperation(installer)) { + ++numInstalled[0]; + } else { + // there was an error, abort. + monitor.error(null, "Install of package failed due to an error"); + monitor.setProgressMax(0); + break; + } + if (monitor.isCancelRequested()) { + break; + } + monitor.incProgress(nextProgress - monitor.getProgress()); + } +/* TODO - Complete post package install operations + if (installedAddon) { + // Update the USB vendor ids for adb + try { + mSdkManager.updateAdb(); + monitor.log("Updated ADB to support the USB devices declared in the SDK add-ons."); + } catch (Exception e) { + mSdkLog.error(e, "Update ADB failed"); + monitor.logError("failed to update adb to support the USB devices declared in the SDK add-ons."); + } + } + + if (preInstallHookInvoked) { + broadcastPostInstallHook(); + } + + if (installedAddon || installedPlatformTools) { + // We need to restart ADB. Actually since we don't know if it's even + // running, maybe we should just kill it and not start it. + // Note: it turns out even under Windows we don't need to kill adb + // before updating the tools folder, as adb.exe is (surprisingly) not + // locked. + + askForAdbRestart(monitor); + } + + if (installedTools) { + notifyToolsNeedsToBeRestarted(flags); + } +*/ + } + }); + + return numInstalled[0]; + } + + private Downloader downloaderInstance() + { + FileSystemFileOp fop = (FileSystemFileOp)FileOpUtils.create(); + return new LegacyDownloader(fop, sdkContext.getSettings()); + } + + private boolean applyPackageOperation( + @NonNull PackageOperation operation) { + ProgressIndicator progressIndicator = sdkContext.getProgressIndicator(); + return operation.prepare(progressIndicator) && operation.complete(progressIndicator); + } + + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/Settings.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/Settings.java new file mode 100644 index 00000000..d080f229 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/Settings.java @@ -0,0 +1,88 @@ +package com.android.sdkuilib.internal.repository; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import com.android.annotations.Nullable; +import com.android.prefs.AndroidLocation; +import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.repository.api.Channel; +import com.android.repository.api.SettingsController; +import com.android.repository.io.FileOp; +import com.android.repository.io.FileOpUtils; +import com.android.repository.io.impl.FileSystemFileOp; +import com.android.utils.ILogger; + +public class Settings implements SettingsController { + + private static final String SETTINGS_FILENAME = "androidtool.cfg"; + public static final String FORCE_HTTP_KEY = "sdkman.force.http"; + + private int mChannel = 0; + private final FileOp mFileOp; + private final Properties mProperties; + + public Settings() + { + mProperties = new Properties(); + mFileOp = (FileSystemFileOp)FileOpUtils.create(); + } + + public boolean getEnablePreviews() { + return true; + } + + @Override + public boolean getForceHttp() { + return Boolean.parseBoolean(this.mProperties.getProperty(FORCE_HTTP_KEY)); + } + + @Override + public void setForceHttp(boolean force) { + mProperties.setProperty(FORCE_HTTP_KEY, Boolean.toString(force)); + } + + @Nullable + @Override + public Channel getChannel() { + return Channel.create(mChannel); + } + + public boolean initialize(ILogger logger) { + try { + loadSettings(); + } catch (AndroidLocationException | IOException e) { + logger.error(e, "Error initializing SDK settings"); + return false; + } + return true; + } + + + private void loadSettings() throws AndroidLocationException, IOException + { + String folder = AndroidLocation.getFolder(); + File file = new File(folder, SETTINGS_FILENAME); + + mProperties.clear(); + mProperties.load(mFileOp.newFileInputStream(file)); + + //setShowUpdateOnly(getShowUpdateOnly()); + //setSetting("sdkman.ask.adb.restart", getAskBeforeAdbRestart()); + //setSetting("sdkman.use.dl.cache", getUseDownloadCache()); + //setSetting("sdkman.enable.previews2", getEnablePreviews()); + } + + public Settings copy() { + Settings copy = new Settings(); + // Load is not expected to fail. Copy will contain defaults if it does. + try { + copy.loadSettings(); + } catch (AndroidLocationException e) { + } catch (IOException e) { + } + return copy; + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SettingsDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SettingsDialog.java index 06a9df9f..029fd936 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SettingsDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SettingsDialog.java @@ -16,14 +16,15 @@ package com.android.sdkuilib.internal.repository; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.DownloadCache.Strategy; -import com.android.sdklib.internal.repository.updater.ISettingsPage; -import com.android.sdklib.internal.repository.updater.SettingsController; -import com.android.sdklib.util.FormatUtils; +//import com.android.sdklib.repository.legacy.remote.internal.DownloadCache; +//import com.android.sdklib.repository.legacy.remote.internal.DownloadCache.Strategy; +//import com.android.sdklib.internal.repository.updater.ISettingsPage; +//import com.android.sdklib.internal.repository.updater.SettingsController; +//import com.android.sdklib.util.FormatUtils; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridLayoutBuilder; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; @@ -39,22 +40,23 @@ import java.util.Properties; -public class SettingsDialog extends UpdaterBaseDialog implements ISettingsPage { +public class SettingsDialog extends UpdaterBaseDialog { // data members - private final DownloadCache mDownloadCache = new DownloadCache(Strategy.SERVE_CACHE); - private final SettingsController mSettingsController; - private SettingsChangedCallback mSettingsChangedCallback; +// private final DownloadCache mDownloadCache = new DownloadCache(Strategy.SERVE_CACHE); +// private final SettingsController mSettingsController; +// private SettingsChangedCallback mSettingsChangedCallback; // UI widgets - private Text mTextProxyServer; - private Text mTextProxyPort; - private Text mTextCacheSize; - private Button mCheckUseCache; +// private Text mTextProxyServer; +// private Text mTextProxyPort; + // TODO - Add channel configuration + private Text mTextChannel; +// private Button mCheckUseCache; private Button mCheckForceHttp; - private Button mCheckAskAdbRestart; - private Button mCheckEnablePreviews; +// private Button mCheckAskAdbRestart; +// private Button mCheckEnablePreviews; private SelectionAdapter mApplyOnSelected = new SelectionAdapter() { @Override @@ -70,10 +72,8 @@ public void modifyText(ModifyEvent e) { } }; - public SettingsDialog(Shell parentShell, SwtUpdaterData swtUpdaterData) { - super(parentShell, swtUpdaterData, "Settings" /*title*/); - assert swtUpdaterData != null; - mSettingsController = swtUpdaterData.getSettingsController(); + public SettingsDialog(Shell parentShell, SdkContext sdkContext) { + super(parentShell, sdkContext, "Settings" /*title*/); } @Override @@ -88,7 +88,7 @@ protected void createShell() { protected void createContents() { super.createContents(); Shell shell = getShell(); - + /* Group group = new Group(shell, SWT.NONE); group.setText("Proxy Settings"); GridDataBuilder.create(group).fill().grab().hSpan(2); @@ -100,7 +100,6 @@ protected void createContents() { String tooltip = "The hostname or IP of the HTTP & HTTPS proxy server to use (e.g. proxy.example.com).\n" + "When empty, the default Java proxy setting is used."; label.setToolTipText(tooltip); - mTextProxyServer = new Text(group, SWT.BORDER); GridDataBuilder.create(mTextProxyServer).hFill().hGrab().vCenter(); mTextProxyServer.addModifyListener(mApplyOnModified); @@ -163,10 +162,10 @@ public void widgetSelected(SelectionEvent arg0) { updateDownloadCacheSize(); } }); - +*/ // ---- - group = new Group(shell, SWT.NONE); - group.setText("Others"); + Group group = new Group(shell, SWT.NONE); + group.setText("Options"); GridDataBuilder.create(group).fill().grab().hSpan(2); GridLayoutBuilder.create(group).columns(2); @@ -177,7 +176,7 @@ public void widgetSelected(SelectionEvent arg0) { "If you are not able to connect to the official Android repository using HTTPS,\n" + "enable this setting to force accessing it via HTTP."); mCheckForceHttp.addSelectionListener(mApplyOnSelected); - +/* mCheckAskAdbRestart = new Button(group, SWT.CHECK); GridDataBuilder.create(mCheckAskAdbRestart).hFill().hGrab().vCenter().hSpan(2); mCheckAskAdbRestart.setText("Ask before restarting ADB"); @@ -185,7 +184,6 @@ public void widgetSelected(SelectionEvent arg0) { "When checked, the user will be asked for permission to restart ADB\n" + "after updating an addon-on package or a tool package."); mCheckAskAdbRestart.addSelectionListener(mApplyOnSelected); - mCheckEnablePreviews = new Button(group, SWT.CHECK); GridDataBuilder.create(mCheckEnablePreviews).hFill().hGrab().vCenter().hSpan(2); mCheckEnablePreviews.setText("Enable Preview Tools"); @@ -194,6 +192,7 @@ public void widgetSelected(SelectionEvent arg0) { "These are optional future release candidates that the Android tools team\n" + "publishes from time to time for early feedback."); mCheckEnablePreviews.addSelectionListener(mApplyOnSelected); +*/ Label filler = new Label(shell, SWT.NONE); GridDataBuilder.create(filler).hFill().hGrab(); @@ -204,14 +203,13 @@ public void widgetSelected(SelectionEvent arg0) { @Override protected void postCreate() { super.postCreate(); - // This tells the controller to load the settings into the page UI. - mSettingsController.setSettingsPage(this); + loadSettings(); } @Override protected void close() { // Dissociate this page from the controller - mSettingsController.setSettingsPage(null); + //mSettingsController.setSettingsPage(null); super.close(); } @@ -221,35 +219,32 @@ protected void close() { //$hide>>$ /** Loads settings from the given {@link Properties} container and update the page UI. */ - @Override - public void loadSettings(Properties inSettings) { - mTextProxyServer.setText(inSettings.getProperty(KEY_HTTP_PROXY_HOST, "")); //$NON-NLS-1$ - mTextProxyPort.setText( inSettings.getProperty(KEY_HTTP_PROXY_PORT, "")); //$NON-NLS-1$ - mCheckForceHttp.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_FORCE_HTTP))); - mCheckAskAdbRestart.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_ASK_ADB_RESTART))); - mCheckUseCache.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_USE_DOWNLOAD_CACHE))); - mCheckEnablePreviews.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_ENABLE_PREVIEWS))); + public void loadSettings() { + Settings settings = mSdkContext.getSettings(); + //mTextProxyServer.setText(inSettings.getProperty(KEY_HTTP_PROXY_HOST, "")); //$NON-NLS-1$ + //mTextProxyPort.setText( inSettings.getProperty(KEY_HTTP_PROXY_PORT, "")); //$NON-NLS-1$ + mCheckForceHttp.setSelection(settings.getForceHttp()); + //mCheckAskAdbRestart.setSelection( + // Boolean.parseBoolean(inSettings.getProperty(KEY_ASK_ADB_RESTART))); + //mCheckUseCache.setSelection( + // Boolean.parseBoolean(inSettings.getProperty(KEY_USE_DOWNLOAD_CACHE))); + //mCheckEnablePreviews.setSelection(false); } /** Called by the application to retrieve settings from the UI and store them in * the given {@link Properties} container. */ - @Override - public void retrieveSettings(Properties outSettings) { - outSettings.setProperty(KEY_HTTP_PROXY_HOST, mTextProxyServer.getText()); - outSettings.setProperty(KEY_HTTP_PROXY_PORT, mTextProxyPort.getText()); - outSettings.setProperty(KEY_FORCE_HTTP, - Boolean.toString(mCheckForceHttp.getSelection())); - outSettings.setProperty(KEY_ASK_ADB_RESTART, - Boolean.toString(mCheckAskAdbRestart.getSelection())); - outSettings.setProperty(KEY_USE_DOWNLOAD_CACHE, - Boolean.toString(mCheckUseCache.getSelection())); - outSettings.setProperty(KEY_ENABLE_PREVIEWS, - Boolean.toString(mCheckEnablePreviews.getSelection())); + public void retrieveSettings() { + Settings settings = mSdkContext.getSettings(); + //outSettings.setProperty(KEY_HTTP_PROXY_HOST, mTextProxyServer.getText()); + //outSettings.setProperty(KEY_HTTP_PROXY_PORT, mTextProxyPort.getText()); + settings.setForceHttp(mCheckForceHttp.getSelection()); + //outSettings.setProperty(KEY_ASK_ADB_RESTART, + // Boolean.toString(mCheckAskAdbRestart.getSelection())); + //outSettings.setProperty(KEY_USE_DOWNLOAD_CACHE, + // Boolean.toString(mCheckUseCache.getSelection())); + //outSettings.setProperty(KEY_ENABLE_PREVIEWS, + // Boolean.toString(mCheckEnablePreviews.getSelection())); } @@ -258,28 +253,26 @@ public void retrieveSettings(Properties outSettings) { * settings must be applied. The page does not apply the settings itself, instead * it notifies the application. */ - @Override + /* public void setOnSettingsChanged(SettingsChangedCallback settingsChangedCallback) { mSettingsChangedCallback = settingsChangedCallback; } - +*/ /** * Callback invoked when user touches one of the settings. * There is no "Apply" button, settings are applied immediately as they are changed. * Notify the application that settings have changed. */ private void applyNewSettings() { - if (mSettingsChangedCallback != null) { - mSettingsChangedCallback.onSettingsChanged(this); - } + retrieveSettings(); } - +/* private void updateDownloadCacheSize() { long size = mDownloadCache.getCurrentSize(); String str = FormatUtils.byteSizeToString(size); mTextCacheSize.setText(str); } - +*/ // End of hiding from SWT Designer //$hide<<$ diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SwtUpdaterData.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SwtUpdaterData.java deleted file mode 100644 index 0d26a3f8..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SwtUpdaterData.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2013 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.sdkuilib.internal.repository; - -import com.android.annotations.NonNull; -import com.android.sdklib.internal.repository.AdbWrapper; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.updater.ArchiveInfo; -import com.android.sdklib.internal.repository.updater.SdkUpdaterLogic; -import com.android.sdklib.internal.repository.updater.UpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; -import com.android.utils.ILogger; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Data shared between {@link SdkUpdaterWindowImpl2} and its pages. - */ -public class SwtUpdaterData extends UpdaterData { - - private Shell mWindowShell; - - /** - * The current {@link ImageFactory}. - * Set via {@link #setImageFactory(ImageFactory)} by the window implementation. - * It is null when invoked using the command-line interface. - */ - private ImageFactory mImageFactory; - - /** - * Creates a new updater data. - * - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - */ - public SwtUpdaterData(String osSdkRoot, ILogger sdkLog) { - super(osSdkRoot, sdkLog); - } - - // ----- getters, setters ---- - - public void setImageFactory(ImageFactory imageFactory) { - mImageFactory = imageFactory; - } - - public ImageFactory getImageFactory() { - return mImageFactory; - } - - public void setWindowShell(Shell windowShell) { - mWindowShell = windowShell; - } - - public Shell getWindowShell() { - return mWindowShell; - } - - @Override - protected void displayInitError(String error) { - // We may not have any UI. Only display a dialog if there's a window shell available. - if (mWindowShell != null && !mWindowShell.isDisposed()) { - MessageDialog.openError(mWindowShell, - "Android Virtual Devices Manager", - error); - } else { - super.displayInitError(error); - } - } - - // ----- - - /** - * Runs the runnable on the UI thread using {@link Display#syncExec(Runnable)}. - * - * @param r Non-null runnable. - */ - @Override - protected void runOnUiThread(@NonNull Runnable r) { - if (mWindowShell != null && !mWindowShell.isDisposed()) { - mWindowShell.getDisplay().syncExec(r); - } - } - - /** - * Attempts to restart ADB. - *

- * If the "ask before restart" setting is set (the default), prompt the user whether - * now is a good time to restart ADB. - */ - @Override - protected void askForAdbRestart(ITaskMonitor monitor) { - final boolean[] canRestart = new boolean[] { true }; - - if (getWindowShell() != null && - getSettingsController().getSettings().getAskBeforeAdbRestart()) { - // need to ask for permission first - final Shell shell = getWindowShell(); - if (shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!shell.isDisposed()) { - canRestart[0] = MessageDialog.openQuestion(shell, - "ADB Restart", - "A package that depends on ADB has been updated. \n" + - "Do you want to restart ADB now?"); - } - } - }); - } - } - - if (canRestart[0]) { - AdbWrapper adb = new AdbWrapper(getOsSdkRoot(), monitor); - adb.stopAdb(); - adb.startAdb(); - } - } - - @Override - protected void notifyToolsNeedsToBeRestarted(int flags) { - String msg = null; - if ((flags & TOOLS_MSG_UPDATED_FROM_ADT) != 0) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "Please also run Eclipse > Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - - } else if ((flags & TOOLS_MSG_UPDATED_FROM_SDKMAN) != 0) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "It is recommended that you now close the manager window and re-open it. " + - "If you use Eclipse, please run Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - } - - final String msg2 = msg; - - final Shell shell = getWindowShell(); - if (msg2 != null && shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!shell.isDisposed()) { - MessageDialog.openInformation(shell, - "Android Tools Updated", - msg2); - } - } - }); - } - } - - /** - * Tries to update all the *existing* local packages. - * This version *requires* to be run with a GUI. - *

- * There are two modes of operation: - *

    - *
  • If selectedArchives is null, refreshes all sources, compares the available remote - * packages with the current local ones and suggest updates to be done to the user (including - * new platforms that the users doesn't have yet). - *
  • If selectedArchives is not null, this represents a list of archives/packages that - * the user wants to install or update, so just process these. - *
- * - * @param selectedArchives The list of remote archives to consider for the update. - * This can be null, in which case a list of remote archive is fetched from all - * available sources. - * @param includeObsoletes True if obsolete packages should be used when resolving what - * to update. - * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. - * @return A list of archives that have been installed. Can be null if nothing was done. - */ - @Override - public List updateOrInstallAll_WithGUI( - Collection selectedArchives, - boolean includeObsoletes, - int flags) { - - // Note: we no longer call refreshSources(true) here. This will be done - // automatically by computeUpdates() iif it needs to access sources to - // resolve missing dependencies. - - SdkUpdaterLogic ul = new SdkUpdaterLogic(this); - List archives = ul.computeUpdates( - selectedArchives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - - if (selectedArchives == null) { - getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog())); - ul.addNewPlatforms( - archives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - } - - // TODO if selectedArchives is null and archives.len==0, find if there are - // any new platform we can suggest to install instead. - - Collections.sort(archives); - - SdkUpdaterChooserDialog dialog = - new SdkUpdaterChooserDialog(getWindowShell(), this, archives); - dialog.open(); - - ArrayList result = dialog.getResult(); - if (result != null && result.size() > 0) { - return installArchives(result, flags); - } - return null; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java index bc8d9d51..f1123f1f 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java @@ -17,12 +17,13 @@ package com.android.sdkuilib.internal.repository; import com.android.SdkConstants; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; +import org.eclipse.andmore.base.resources.ImageFactory; +//import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridLayoutBuilder; import com.android.sdkuilib.ui.SwtBaseDialog; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -36,18 +37,19 @@ * about box or add-on site.) */ public abstract class UpdaterBaseDialog extends SwtBaseDialog { + public static final String APP_NAME = "Android SDK Manager"; - private final SwtUpdaterData mSwtUpdaterData; + protected final SdkContext mSdkContext; - protected UpdaterBaseDialog(Shell parentShell, SwtUpdaterData swtUpdaterData, String title) { + protected UpdaterBaseDialog(Shell parentShell, SdkContext sdkContext, String title) { super(parentShell, SWT.APPLICATION_MODAL, - String.format("%1$s - %2$s", SdkUpdaterWindowImpl2.APP_NAME, title)); //$NON-NLS-1$ - mSwtUpdaterData = swtUpdaterData; + String.format("%1$s - %2$s", APP_NAME, title)); //$NON-NLS-1$ + mSdkContext = sdkContext; } - public SwtUpdaterData getSwtUpdaterData() { - return mSwtUpdaterData; + public SdkContext getSdkContext() { + return mSdkContext; } /** @@ -96,11 +98,9 @@ private void setWindowImage(Shell shell) { imageName = "android_icon_128.png"; //$NON-NLS-1$ } - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); - if (imgFactory != null) { - shell.setImage(imgFactory.getImageByName(imageName)); - } + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); + if (imgFactory != null) { + shell.setImage(imgFactory.getImageByName(imageName)); } } } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UserCredentials.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UserCredentials.java similarity index 87% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UserCredentials.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UserCredentials.java index 62949564..c3e55d1c 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/repository/UserCredentials.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/UserCredentials.java @@ -1,53 +1,50 @@ -/* - * Copyright (C) 2011 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.internal.repository; - -/** - * @deprecated - * com.android.sdklib.internal.repository has moved into Studio as - * com.android.tools.idea.sdk.remote.internal. - */ -@Deprecated -public class UserCredentials { - private final String mUserName; - private final String mPassword; - private final String mWorkstation; - private final String mDomain; - - public UserCredentials(String userName, String password, String workstation, String domain) { - mUserName = userName; - mPassword = password; - mWorkstation = workstation; - mDomain = domain; - } - - public String getUserName() { - return mUserName; - } - - public String getPassword() { - return mPassword; - } - - public String getWorkstation() { - return mWorkstation; - } - - public String getDomain() { - return mDomain; - } -} +/* + * Copyright (C) 2011 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.sdkuilib.internal.repository; + +/** + * User authentication details + */ +public class UserCredentials { + private final String mUserName; + private final String mPassword; + private final String mWorkstation; + private final String mDomain; + + public UserCredentials(String userName, String password, String workstation, String domain) { + mUserName = userName; + mPassword = password; + mWorkstation = workstation; + mDomain = domain; + } + + public String getUserName() { + return mUserName; + } + + public String getPassword() { + return mPassword; + } + + public String getWorkstation() { + return mWorkstation; + } + + public String getDomain() { + return mDomain; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/AvdAgent.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/AvdAgent.java new file mode 100644 index 00000000..f335f369 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/AvdAgent.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository.avd; + +import java.util.Map; + +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.SdkVersionInfo; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.IdDisplay; +import com.android.sdklib.repository.meta.DetailsTypes; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.content.PackageType; + +/** + * @author Andrew Bowley + * + * 15-11-2017 + */ +public class AvdAgent { + + private static final String BLANK = ""; + private final AvdInfo avd; + private final IAndroidTarget target; + private String deviceName; + private String deviceMfctr; + private String path; + private SystemImage systemImage; + private String platformVersion; + private String versionWithCodename; + private AndroidVersion androidVersion; + private PackageType packageType; + private String vendor; + private String targetDisplayName; + private String skin; + private String sdcard; + private String snapshot; + + /** + * + */ + public AvdAgent(IAndroidTarget target, AvdInfo avd) { + this.target = target; + this.avd = avd; + path = avd.getDataFolderPath(); + systemImage = (SystemImage) avd.getSystemImage(); + vendor = BLANK; + targetDisplayName = BLANK; + init(); + } + + public AvdInfo getAvd() { + return avd; + } + + public IAndroidTarget getTarget() + { + return target; + } + + public String getDeviceName() { + return deviceName; + } + + public String getDeviceMfctr() { + return deviceMfctr; + } + + public String getPath() { + return path; + } + + public SystemImage getSystemImage() { + return systemImage; + } + + public String getPlatformVersion() { + return platformVersion; + } + + public String getVersionWithCodename() { + return versionWithCodename; + } + + public AndroidVersion getAndroidVersion() { + return androidVersion; + } + + public PackageType getPackageType() { + return packageType; + } + + public String getVendor() { + return vendor; + } + + public String getTargetFullName() { + return target.getFullName(); + } + + public String getTargetVersionName() { + return target.getVersionName(); + } + + public String getTargetDisplayName() { + return targetDisplayName; + } + + public String getSkin() { + return skin; + } + + public String getSdcard() { + return sdcard; + } + + public String getSnapshot() { + return snapshot; + } + + public String getPrettyAbiType() { + return AvdInfo.getPrettyAbiType(avd); + } + + private void init() + { + deviceName = avd.getProperties().get(AvdManager.AVD_INI_DEVICE_NAME); + deviceMfctr = avd.getProperties().get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + if (deviceName == null) { + deviceName = BLANK; + deviceMfctr = BLANK; + } + else if (deviceMfctr == null) + deviceMfctr = BLANK; + DetailsTypes.ApiDetailsType details = + (DetailsTypes.ApiDetailsType) systemImage.getPackage().getTypeDetails(); + androidVersion = details.getAndroidVersion(); + versionWithCodename = SdkVersionInfo + .getVersionWithCodename(androidVersion); + platformVersion = SdkVersionInfo.getVersionString(androidVersion.getApiLevel()); + if (details instanceof DetailsTypes.PlatformDetailsType) { + packageType = PackageType.platforms; + } else if (details instanceof DetailsTypes.SysImgDetailsType) { + packageType = PackageType.system_images; + IdDisplay vendorId = ((DetailsTypes.SysImgDetailsType) details).getVendor(); + if (vendorId != null) { + vendor = vendorId.getDisplay(); + } + } else if (details instanceof DetailsTypes.AddonDetailsType) { + packageType = PackageType.add_ons; + vendor = ((DetailsTypes.AddonDetailsType) details).getVendor().getDisplay(); + } + if (target.isPlatform()) { + targetDisplayName = String.format(" API: %s", versionWithCodename); + } else { + targetDisplayName = + String.format("Target: %s\n" + + " Based on %s)", + target.getFullName(), + target.getParent().getFullName()); + } + // Some extra values. + Map properties = avd.getProperties(); + skin = properties.get(AvdManager.AVD_INI_SKIN_NAME); + sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE); + if (sdcard == null) + sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH); + if (sdcard == null) + sdcard = BLANK; + snapshot = properties.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); + if (snapshot == null) + snapshot = BLANK; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/SdkTargets.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/SdkTargets.java new file mode 100644 index 00000000..0df8b847 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/avd/SdkTargets.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository.avd; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import org.eclipse.andmore.sdktool.SdkContext; + +import com.android.repository.api.ProgressIndicator; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.repository.IdDisplay; +import com.android.sdklib.repository.meta.DetailsTypes; +import com.android.sdklib.repository.targets.AddonTarget; +import com.android.sdklib.repository.targets.PlatformTarget; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.content.PackageType; + +/** + * @author Andrew Bowley + * + * 16-11-2017 + */ +public class SdkTargets { + + private final List targets = new ArrayList<>(); + private final Collection sysImages; + private final Map targetMap = new HashMap<>(); + + /** + * + */ + public SdkTargets(SdkContext sdkContext) { + ProgressIndicator progress = sdkContext.getProgressIndicator(); + targets.addAll( + sdkContext.getHandler().getAndroidTargetManager(progress) + .getTargets(progress)); + Collections.sort(targets, new Comparator(){ + + @Override + public int compare(IAndroidTarget target1, IAndroidTarget target2) { + return getApiLevel(target1) - getApiLevel(target2); + }}); + + sysImages = + sdkContext.getHandler().getSystemImageManager(progress).getImages(); + Iterator iterator = sysImages.iterator(); + while(iterator.hasNext()) { + SystemImage systemImage = iterator.next(); + IAndroidTarget target = mapTarget(systemImage); + if (target != null) + targetMap.put(systemImage, target); + } + + } + + public List getSystemImages(IAndroidTarget target) { + List systemImages = new ArrayList<>(); + Set> targetEntries = targetMap.entrySet(); + Iterator> iterator = targetEntries.iterator(); + while(iterator.hasNext()) { + Entry entry = iterator.next(); + if (entry.getValue().canRunOn(target)) + systemImages.add(entry.getKey()); + } + // Sort + Collections.sort(systemImages, new Comparator(){ + + @Override + public int compare(SystemImage sysImage1, SystemImage sysImage2) { + return sysImage1.compareTo(sysImage2); + }}); + // Remove duplicates which contain same abitype details + // Prior sort ensures predictable results + Set abiTypeSet = new HashSet<>(); + Iterator imagesIterator = systemImages.iterator(); + while (imagesIterator.hasNext()) { + SystemImage systemImage = imagesIterator.next(); + String key = AvdInfo.getPrettyAbiType(systemImage); + if (abiTypeSet.contains(key)) + imagesIterator.remove(); + else + abiTypeSet.add(key); + } + return systemImages; + } + + public Map getTargetMap() + { + return Collections.unmodifiableMap(targetMap); + } + + public Collection getTargets() { + return targets; + } + + public Collection getSysImages() { + return sysImages; + } + + public IAndroidTarget getTargetForSysImage(SystemImage systemImage) { + return targetMap.get(systemImage); + } + + IAndroidTarget mapTarget(SystemImage systemImage) { + PackageType packageType = null; + IdDisplay vendorId = IdDisplay.create("", ""); + DetailsTypes.ApiDetailsType details = + (DetailsTypes.ApiDetailsType) systemImage.getPackage().getTypeDetails(); + if (details instanceof DetailsTypes.PlatformDetailsType) { + packageType = PackageType.platforms; + } else if (details instanceof DetailsTypes.SysImgDetailsType) { + packageType = PackageType.system_images; + vendorId = ((DetailsTypes.SysImgDetailsType) details).getVendor(); + } else if (details instanceof DetailsTypes.AddonDetailsType) { + packageType = PackageType.add_ons; + vendorId = ((DetailsTypes.AddonDetailsType) details).getVendor(); + } + for (IAndroidTarget target: targets) + { + if (filterOnApi(systemImage, target)) + { + if ((packageType == PackageType.add_ons) && + !target.isPlatform() && + target.getVendor().equals(vendorId.getId())) + return target; + else if (target.isPlatform()) + return target; + } + } + return null; + } + + private boolean filterOnApi(SystemImage systemImage, IAndroidTarget target) + { + int imageApi = systemImage.getAndroidVersion().getApiLevel(); + int targetApi = getApiLevel(target); + return imageApi <= targetApi; + } + + private int getApiLevel(IAndroidTarget target) { + if (target.isPlatform()) { + PlatformTarget plaformTarget = (PlatformTarget)target; + return plaformTarget.getVersion().getApiLevel(); + } + AddonTarget addonTarget = (AddonTarget)target; + return addonTarget.getParent().getVersion().getApiLevel(); + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/CategoryKeyType.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/CategoryKeyType.java new file mode 100644 index 00000000..b8d703f3 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/CategoryKeyType.java @@ -0,0 +1,10 @@ +package com.android.sdkuilib.internal.repository.content; + +public enum CategoryKeyType { + TOOLS, + TOOLS_PREVIEW, + API, + EXTRA, + LOCAL, + REMOTE +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/INode.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/INode.java new file mode 100644 index 00000000..dea81e15 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/INode.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository.content; + +import java.util.Collections; +import java.util.List; + +import com.android.sdkuilib.internal.repository.content.PackageAnalyser.PkgState; + +/** + * Tree node which provides the text, font and image for the label of a given tree element + * @author Andrew Bowley + * + */ +public class INode { + /** Font can be normal or italic */ + static enum LabelFont { normal, italic } + + static final List EMPTY_NODE_LIST; + static final String VOID = ""; + + static + { + EMPTY_NODE_LIST = Collections.emptyList(); + } + + /** Flag to mirror node checkbox state */ + protected boolean isChecked; + + /** + * Returns the image resource value for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the resource value of image used to label the element, or VOID if there is no image for the given object + */ + public String getImage(Object element, int columnIndex) { + return VOID; + } + + /** + * Returns the text for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the text string used to label the element, or VOID if there is no text label for the given object + */ + public String getText(Object element, int columnIndex) { + return VOID; + } + + /** + * Provides a font for the given element at index columnIndex. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return LabelFont.normal or LabelFont.italic + */ + public LabelFont getFont(Object element, int columnIndex) { + return LabelFont.normal; + } + + /** + * Get the text displayed in the tool tip for given element + * @param element Target + * @return the tooltop text, or VOID for no text to display + */ + public String getToolTipText(Object element) { + return VOID; + } + + /** + * Returns list of descendents + * @return INode list + */ + public List getChildren() { + return EMPTY_NODE_LIST; + } + + /** + * Returns checkbox state + * @return boolean + */ + public boolean isChecked() { + return isChecked; + } + + /** + * Sets checkbox state + * @param isChecked Value to set checkbox on next refresh + */ + public void setChecked(boolean isChecked) { + this.isChecked = isChecked; + } + + /** + * Mark item as checked according to given criteria. Force uncheck if no criteria specified. + * @param selectUpdates If true, select all update packages + * @param topApiLevel If greater than 0, select platform packages of this api level + */ + public void checkSelections( + boolean selectUpdates, + int topApiLevel) + { + } + + public void markDeleted() + { + } + + public boolean isDeleted() + { + return false; + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/MetaPackage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/MetaPackage.java new file mode 100644 index 00000000..5af460dd --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/MetaPackage.java @@ -0,0 +1,28 @@ +package com.android.sdkuilib.internal.repository.content; + +/** + * Information about a package type + */ +public class MetaPackage { + + private final PackageType mPackageType; + private final String mIconResource; + + public MetaPackage(PackageType packageType, String iconResource) { + this.mPackageType = packageType; + this.mIconResource = iconResource; + } + + public PackageType getPackageType() { + return mPackageType; + } + + public String getIconResource() { + return mIconResource; + } + + public String getName() + { + return mPackageType.toString().replaceAll("_", "-"); + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageAnalyser.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageAnalyser.java new file mode 100644 index 00000000..bab62caf --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageAnalyser.java @@ -0,0 +1,304 @@ +package com.android.sdkuilib.internal.repository.content; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.andmore.sdktool.SdkContext; + +import com.android.SdkConstants; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoPackage; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.TypeDetails; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.repository.meta.DetailsTypes; +import com.android.sdkuilib.internal.repository.PackageManager.UpdatablePackageHandler; +import com.android.sdkuilib.internal.repository.content.UpdateOp.SdkSource; + +public class PackageAnalyser { + public static final String GENERIC = "generic"; + + private final SdkContext mSdkContext; + private final UpdateOpApi mOpApi; + private final Map mMetaPackageMap = new HashMap<>(); + private boolean mFirstLoadComplete = true; + + /** + * {@link PkgState}s to check in {@link #processSource(UpdateOp, SdkSource, Package[])}. + */ + public static enum PkgState { INSTALLED, NEW, DELETED }; + + public PackageAnalyser(SdkContext sdkContext) + { + this.mSdkContext = sdkContext; + mOpApi = new UpdateOpApi(); + initMetaPackages(); + } + + public MetaPackage getMetaPackage(String name) + { + return mMetaPackageMap.get(name); + } + + /** + * Removes all the internal state and resets the object. + * Useful for testing. + */ + public void clear() { + mFirstLoadComplete = true; + mOpApi.clear(); + } + + /** Return mFirstLoadComplete and resets it to false. + * All following calls will returns false. */ + public boolean isFirstLoadComplete() { + boolean b = mFirstLoadComplete; + mFirstLoadComplete = false; + return b; + } + + + /** + * Mark all new and update PkgItems as checked. + * + * @param selectNew If true, select all new packages (except the rc/preview ones). + * @param selectUpdates If true, select all update packages. + * @param selectTop If true, select the top platform. All new packages are selected, excluding system images and + * rc/preview. Packages to update are selected regardless. + * @param currentPlatform The {@link SdkConstants#currentPlatform()} value. + */ + public void checkNewUpdateItems( + boolean selectUpdates, + boolean selectTop) { + int apiLevel = 0; + if (selectTop) { + for (PkgCategory cat: mOpApi.getCategories()) + { + // Find first API category to get top API + if (cat.getKeyType() == CategoryKeyType.API) { + PkgCategoryApi pkgCategoryApi = (PkgCategoryApi)cat; + apiLevel = pkgCategoryApi.getKeyValue().getApiLevel(); + break; + } + } + } + for (PkgCategory cat: mOpApi.getCategories()) + checkNode(cat, selectUpdates, apiLevel, 0); + } + + private void checkNode(INode node, boolean selectUpdates, int topApiLevel, int level) + { + node.checkSelections(selectUpdates, topApiLevel); + for (INode child: node.getChildren()) + checkNode(child, selectUpdates, topApiLevel, level+ 1); + } + + /** + * Mark all PkgItems as not checked. + */ + public void uncheckAllItems() { + for (PkgCategory cat: mOpApi.getCategories()) + checkNode(cat, false, 0, 0); + } + + public List> getApiCategories() { + return mOpApi.getCategories(); + } + + public List getAllPkgItems() { + List items = new ArrayList(); + + List> cats = getApiCategories(); + synchronized (cats) { + for (PkgCategory cat : cats) { + items.addAll(cat.getItems()); + } + } + return items; + } + + public void updateStart() { + mOpApi.updateStart(); + } + + public void removeDeletedNodes() { + for (PkgCategory cat: mOpApi.getCategories()) + remoteDeleted(cat, 0); + } + + private void remoteDeleted(INode node, int level) { + List removeList = null; + for (INode childNode: node.getChildren()) { + if (childNode.isDeleted()) { + if (removeList == null) + removeList = new ArrayList<>(); + removeList.add(childNode); + } + remoteDeleted(childNode, level + 1); + } + if (removeList != null) { + for (INode removeNode: removeList) { + node.getChildren().remove(removeNode); + } + } + } + + public boolean updateSourcePackages(SdkSource source, RepoPackage[] newPackages) { + + return mOpApi.updateSourcePackages(source, newPackages); + } + + public boolean updateEnd() { + return mOpApi.updateEnd(); + } + + public static String getNameFromPath(String path) + { + int pos = path.indexOf(RepoPackage.PATH_SEPARATOR); + return pos == -1 ? path : path.substring(0, pos); + } + + public static AndroidVersion getAndroidVersion(RepoPackage pkg) { + TypeDetails details = pkg.getTypeDetails(); + if (details instanceof DetailsTypes.ApiDetailsType) { + return ((DetailsTypes.ApiDetailsType)details).getAndroidVersion(); + } + return null; + } + + private void initMetaPackages() { + MetaPackage metaPackage = new MetaPackage(PackageType.tools, "tool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.platform_tools, "platformtool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.build_tools, "buildtool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.platforms, "platform_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.add_ons, "addon_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.system_images, "sysimg_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.sources, "source_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.docs, "doc_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.extras, "extra_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.emulator, "tool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.cmake, "tool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.lldb, "tag_default_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.ndk_bundle, "tag_default_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.patcher, "tool_pkg_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + + metaPackage = new MetaPackage(PackageType.generic, "tag_default_16.png"); + mMetaPackageMap.put(metaPackage.getName(), metaPackage); + } + + public void loadPackages() { + UpdatablePackageHandler updateHandler = new UpdatablePackageHandler(){ + + @Override + public void onPackageLoaded(UpdatablePackage updatePackage) { + updateApiItem(updatePackage); + }}; + // All previous entries must be deleted or duplicates will occur + mOpApi.getCategories().clear(); + mSdkContext.getPackageManager().loadConsolidatedPackages(updateHandler); + mOpApi.sortCategoryList(); + } + + private void updateApiItem(UpdatablePackage updatePackage) { + LocalPackage local = updatePackage.getLocal(); + RemotePackage remote = updatePackage.getRemote(); + PkgCategory cat = null; + PkgItem item = null; + if (local != null) { + cat = getPkgCategory(local); + item = new PkgItem(local, metaPackageFromPackage(local), PkgState.INSTALLED); + if ((remote != null) && !local.getVersion().equals(remote.getVersion())) + item.setUpdatePkg(updatePackage); + } + else { + cat = getPkgCategory(remote); + item = new PkgItem(remote, metaPackageFromPackage(remote), PkgState.NEW); + } + cat.getItems().add(item); + } + + private PkgCategory getPkgCategory(RepoPackage pkg) + { + List> cats = mOpApi.getCategories(); + CategoryKeyType catKeyType = mOpApi.getCategoryKeyType(pkg); + PkgCategory cat = null; + AndroidVersion catKeyValue = null; + switch (catKeyType) + { + case API: + case REMOTE: + catKeyValue = mOpApi.getCategoryKeyValue(pkg); + cat = findCurrentCategory(cats, catKeyType, catKeyValue); + break; + default: + cat = findCurrentCategory(cats, catKeyType); + } + if (cat == null) { + // This is a new category. Create it and add it to the list. + cat = mOpApi.createCategory(catKeyType, catKeyValue); + synchronized (cats) { + cats.add(cat); + } + } + return cat; + } + + private PkgCategory findCurrentCategory( + List> currentCategories, + CategoryKeyType catKeyType) { + for (PkgCategory cat : currentCategories) { + if (cat.getKeyType() == catKeyType) { + return cat; + } + } + return null; + } + + private PkgCategory findCurrentCategory( + List> currentCategories, + CategoryKeyType catKeyType, Object categoryKeyValue) { + for (PkgCategory cat : currentCategories) { + if ((cat.getKeyType() == catKeyType) && (cat.getKeyValue().equals(categoryKeyValue))) + return cat; + } + return null; + } + + private MetaPackage metaPackageFromPackage(RepoPackage repoPackage) + { + String name = PackageAnalyser.getNameFromPath(repoPackage.getPath()); + MetaPackage metaPackage = getMetaPackage(name); + return metaPackage != null ? metaPackage : getMetaPackage(PackageAnalyser.GENERIC); + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageContentProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageContentProvider.java new file mode 100644 index 00000000..9442c62c --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageContentProvider.java @@ -0,0 +1,130 @@ +package com.android.sdkuilib.internal.repository.content; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.andmore.sdktool.SdkContext; +import org.eclipse.jface.viewers.IInputProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoPackage; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.Archive; +import com.android.sdkuilib.internal.repository.PackageManager; + +public class PackageContentProvider implements ITreeContentProvider { + + private final IInputProvider mViewer; + private final SdkContext mSdkContext; + private final PackageManager mPackageManager; + private boolean mDisplayArchives; + + public PackageContentProvider(SdkContext sdkContext, IInputProvider viewer) + { + this.mSdkContext = sdkContext; + this.mViewer = viewer; + this.mPackageManager = sdkContext.getPackageManager(); + } + + public void setDisplayArchives(boolean displayArchives) { + mDisplayArchives = displayArchives; + } + + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof ArrayList) { + return ((ArrayList) parentElement).toArray(); + + } else if (parentElement instanceof PkgCategory) { + return ((PkgCategory) parentElement).getItems().toArray(); + + } else if (parentElement instanceof PkgItem) { + if (mDisplayArchives) { + + UpdatablePackage pkg = ((PkgItem) parentElement).getUpdatePkg(); + + // Display update packages as sub-items if the details mode is activated. + if (pkg != null) { + return new Object[] { pkg }; + } + + return ((PkgItem) parentElement).getArchives(); + } + + } else if (parentElement instanceof RemotePackage) { + if (mDisplayArchives) { + return new Archive[]{((RemotePackage) parentElement).getArchive()}; + } + + } + + return new Object[0]; + } + + @Override + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + @Override + @SuppressWarnings("unchecked") + public Object getParent(Object element) { + // This operation is expensive, so we do the minimum + // and don't try to cover all cases. + + if (element instanceof PkgItem) { + Object input = mViewer.getInput(); + if (input != null) { + for (PkgCategory cat : (List) input) { + if (cat.getItems().contains(element)) { + return cat; + } + } + } + } + + return null; + } + + + @Override + public boolean hasChildren(Object parentElement) { + if (parentElement instanceof ArrayList) { + return true; + + } else if (parentElement instanceof PkgCategory) { + return true; + + } else if (parentElement instanceof PkgItem) { + if (mDisplayArchives) { + UpdatablePackage pkg = ((PkgItem) parentElement).getUpdatePkg(); + + // Display update packages as sub-items if the details mode is activated. + if (pkg != null) { + return true; + } + + Archive[] archives = ((PkgItem) parentElement).getArchives(); + return archives.length > 0; + } + } else if (parentElement instanceof RemotePackage) { + if (mDisplayArchives) { + return ((RemotePackage) parentElement).getArchive() != null; + } + } + + return false; + } + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer arg0, Object arg1, Object arg2) { + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageType.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageType.java new file mode 100644 index 00000000..fd9dc2f3 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PackageType.java @@ -0,0 +1,19 @@ +package com.android.sdkuilib.internal.repository.content; + +public enum PackageType { + tools, + platform_tools, + build_tools, + platforms, + add_ons, + system_images, + sources, + docs, + extras, + emulator, + cmake, + lldb, + ndk_bundle, + patcher, + generic +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategory.java new file mode 100644 index 00000000..9ff07680 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategory.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2011 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.sdkuilib.internal.repository.content; + + +import java.util.ArrayList; +import java.util.List; + +import com.android.sdkuilib.internal.repository.ui.PackagesPage; + +/** + * PkgCategory represents the first level of the package tree + * @author Andrew Bowley + * + * 10-11-2017 + */ +public abstract class PkgCategory extends INode { + protected final CategoryKeyType keyType; + protected final K keyValue; + protected final String imageReference; + protected final List packageList = new ArrayList(); + protected String label; + + public PkgCategory(CategoryKeyType keyType, String label, String imageReference) { + this(keyType, null, label, imageReference); + } + + public PkgCategory(CategoryKeyType keyType, K keyValue, String label, String imageReference) { + super(); + this.keyType = keyType; + this.keyValue = keyValue; + this.label = label; + this.imageReference = imageReference; + } + + public CategoryKeyType getKeyType() + { + return keyType; + } + + public K getKeyValue() { + return keyValue; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public List getItems() { + return packageList; + } + + /** + * Returns the text for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the text string used to label the element + */ + @Override + public String getText(Object element, int columnIndex) { + return columnIndex == PackagesPage.NAME ? getLabel() : VOID; + } + + /** + * Returns the image resource value for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the resource value of image used to label the element + */ + @Override + public String getImage(Object element, int columnIndex) { + if (columnIndex == PackagesPage.NAME) + return imageReference; + return VOID; + } + + /** + * Returns list of descendents + * @return INode list + */ + @Override + public List getChildren() { + return packageList; + } + + @Override + public String toString() { + return String.format("%s ", + this.getClass().getSimpleName(), + keyValue == null ? keyType.toString() : keyValue.toString(), + label, + packageList.size()); + } + + /** {@link PkgCategory}s are equal if their internal keys are equal. */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((keyValue == null) ? keyType.hashCode() : keyValue.hashCode()); + return result; + } + + /** {@link PkgCategory}s are equal if their internal keys are equal. */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + PkgCategory other = (PkgCategory) obj; + if (keyType != other.keyType) + return false; + if (keyValue == null) { + if (other.keyValue != null) return false; + } else if (!keyValue.equals(other.keyValue)) return false; + return true; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategoryApi.java similarity index 65% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategoryApi.java index 89a4914a..1353e01e 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCategoryApi.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.repository.core; +package com.android.sdkuilib.internal.repository.content; import com.android.sdklib.AndroidVersion; +import com.android.sdklib.SdkVersionInfo; -public class PkgCategoryApi extends PkgCategory { +public class PkgCategoryApi extends PkgCategory { /** Platform name, in the form "Android 1.2". Can be null if we don't have the name. */ private String mPlatformName; @@ -29,16 +30,11 @@ public class PkgCategoryApi extends PkgCategory { // We always want categories in order tools..platforms..extras; to achieve that tools // and extras have the special values so they get "naturally" sorted the way we want // them. - // (Note: don't use integer.max to avoid integers wrapping in comparisons. We can - // revisit the day we get 2^30 platforms.) - public final static AndroidVersion KEY_TOOLS = new AndroidVersion(Integer.MAX_VALUE / 2, null); - public final static AndroidVersion KEY_TOOLS_PREVIEW = - new AndroidVersion(Integer.MAX_VALUE / 2 - 1, null); - public final static AndroidVersion KEY_EXTRA = new AndroidVersion(-1, null); - public PkgCategoryApi(AndroidVersion version, String platformName, Object iconRef) { - super(version, null /*label*/, iconRef); - setPlatformName(platformName); + public PkgCategoryApi(CategoryKeyType keyType, AndroidVersion version, String iconRef) { + super(keyType, version, null /*label*/, iconRef); + if (version != null) + setPlatformName(SdkVersionInfo.getVersionWithCodename(version)); } public String getPlatformName() { @@ -54,29 +50,28 @@ public void setPlatformName(String platformName) { } public String getApiLabel() { - AndroidVersion key = (AndroidVersion) getKey(); - if (key.equals(KEY_TOOLS)) { + if (getKeyType() == CategoryKeyType.TOOLS) { return "TOOLS"; //$NON-NLS-1$ // for internal debug use only - } else if (key.equals(KEY_TOOLS_PREVIEW)) { - return "TOOLS-PREVIEW"; //$NON-NLS-1$ // for internal debug use only - } else if (key.equals(KEY_EXTRA)) { + } else if (getKeyType() == CategoryKeyType.TOOLS_PREVIEW){ + return "TOOLS-PREVIEW"; //$NON-NLS-1$ // for internal debug use only + } else if (getKeyType() == CategoryKeyType.EXTRA) { return "EXTRAS"; //$NON-NLS-1$ // for internal debug use only - } else { - return key.toString(); - } - } + } + AndroidVersion key = getKeyValue(); + return key.getApiString(); + } @Override public String getLabel() { String label = super.getLabel(); if (label == null) { - AndroidVersion key = (AndroidVersion) getKey(); + CategoryKeyType key = getKeyType(); - if (key.equals(KEY_TOOLS)) { + if (key == CategoryKeyType.TOOLS) { label = "Tools"; - } else if (key.equals(KEY_TOOLS_PREVIEW)) { + } else if (key == CategoryKeyType.TOOLS_PREVIEW) { label = "Tools (Preview Channel)"; - } else if (key.equals(KEY_EXTRA)) { + } else if (key == CategoryKeyType.EXTRA) { label = "Extras"; } else { if (mPlatformName != null) { diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellAgent.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellAgent.java new file mode 100644 index 00000000..1fadf298 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellAgent.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository.content; + +import java.util.List; + +import org.eclipse.andmore.sdktool.SdkContext; +import org.eclipse.swt.graphics.Font; + +import com.android.sdklib.AndroidVersion; +import org.eclipse.andmore.base.resources.ImageFactory; + +public class PkgCellAgent { + + /** Column identities */ + public static final int NAME = 1; + public static final int API = 2; + public static final int REVISION = 3; + public static final int STATUS = 4; + + private final Font mTreeFontItalic; + private final ImageFactory mImgFactory; + private final List> mCategoryList; + + public PkgCellAgent(SdkContext sdkContext, PackageAnalyser packageAnalyser, Font treeFontItalic) { + this.mTreeFontItalic = treeFontItalic; + this.mImgFactory = sdkContext.getSdkHelper().getImageFactory(); + this.mCategoryList = packageAnalyser.getApiCategories(); + } + + public Font getTreeFontItalic() + { + return mTreeFontItalic; + } + + public ImageFactory getImgFactory() { + return mImgFactory; + } + + public List> getCategoryList() { + return mCategoryList; + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellLabelProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellLabelProvider.java new file mode 100644 index 00000000..dfe38289 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgCellLabelProvider.java @@ -0,0 +1,79 @@ +package com.android.sdkuilib.internal.repository.content; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ITableFontProvider; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import com.android.sdkuilib.internal.repository.content.INode.LabelFont; +import org.eclipse.andmore.base.resources.ImageFactory; + +public class PkgCellLabelProvider extends ColumnLabelProvider implements ITableFontProvider { + + public static final int NAME = 1; + public static final int API = 2; + public static final int REVISION = 3; + public static final int STATUS = 4; + private final int columnIndex; + private final PkgCellAgent agent; + + public PkgCellLabelProvider(PkgCellAgent agent, int columnIndex) { + super(); + this.columnIndex = columnIndex; + this.agent = agent; + } + + @Override + public String getText(Object element) { + INode node = (INode)element; + String text = node.getText(element, columnIndex); + return text != INode.VOID ? text : null; + } + + /** + * The image is owned by the label provider and must not be disposed directly. + */ + @Override + public Image getImage(Object element) { + ImageFactory imgFactory = agent.getImgFactory(); + if (imgFactory != null) { + INode node = (INode)element; + String reference = node.getImage(element, columnIndex); + if (reference != INode.VOID) + return imgFactory.getImageByName(reference); + } + return super.getImage(element); + } + + // -- ITableFontProvider + + @Override + public Font getFont(Object element, int columnIndex) { + INode node = (INode)element; + LabelFont fontType = node.getFont(element, columnIndex); + if (fontType == LabelFont.italic) + return agent.getTreeFontItalic(); + return super.getFont(element); + } + + // -- Tooltip support + @Override + public String getToolTipText(Object element) { + INode node = (INode)element; + String text = node.getToolTipText(element); + if (text != INode.VOID) + return text; + return super.getToolTipText(element); + } + + @Override + public Point getToolTipShift(Object object) { + return new Point(15, 5); + } + + @Override + public int getToolTipDisplayDelayTime(Object object) { + return 500; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgItem.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgItem.java new file mode 100644 index 00000000..6b2535eb --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgItem.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2011 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.sdkuilib.internal.repository.content; + +import java.util.regex.Pattern; + +import org.eclipse.andmore.sdktool.Utilities; + +import com.android.SdkConstants; +import com.android.annotations.Nullable; +import com.android.repository.Revision; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoPackage; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.Archive; +import com.android.repository.impl.meta.TypeDetails; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.repository.meta.DetailsTypes; +import com.android.sdkuilib.internal.repository.content.PackageAnalyser.PkgState; +import com.android.sdkuilib.internal.repository.ui.PackagesPage; +import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; + +/** + * A {@link PkgItem} represents one main {@link Package} combined with its state + * and an optional update package. + *

+ * The main package is final and cannot change since it's what "defines" this PkgItem. + * The state or update package can change later. + */ +public class PkgItem extends INode implements Comparable { + private final MetaPackage metaPackage; + private PkgState state; + private RepoPackage mainPackage; + private UpdatablePackage updatePackage; + + /** + * Create a new {@link PkgItem} for this main package. + * The main package is final and cannot change since it's what "defines" this PkgItem. + * The state or update package can change later. + */ + public PkgItem(RepoPackage mainPkg, MetaPackage metaPackage, PkgState state) { + super(); + this.mainPackage = mainPkg; + this.metaPackage = metaPackage; + this.state = state; + } + + public boolean isObsolete() { + return mainPackage.obsolete(); + } + + public UpdatablePackage getUpdatePkg() { + return updatePackage; + } + + public void setUpdatePkg(UpdatablePackage updatePkg) { + updatePackage = updatePkg; + } + + public boolean hasUpdatePkg() { + return updatePackage != null; + } + + public String getName() { + return mainPackage.getDisplayName(); + } + + public Revision getRevision() { + return mainPackage.getVersion(); + } + + public MetaPackage getMetaPackage() + { + return metaPackage; + } + + public RepoPackage getMainPackage() { + return mainPackage; + } + + public PkgState getState() { + return state; + } + + @Nullable + public AndroidVersion getAndroidVersion() { + return getAndroidVersion(mainPackage); + } + + public Archive[] getArchives() { + if (state == PkgState.NEW) + return new Archive[]{((RemotePackage)mainPackage).getArchive()}; + return new Archive[0]; + } + + /** + * Returns the image resource value for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the resource value of image used to label the element + */ + @Override + public String getImage(Object element, int columnIndex) { + if (columnIndex == PackagesPage.NAME) + return metaPackage.getIconResource(); + else if (columnIndex == PackagesPage.STATUS) { + switch(state) { + case INSTALLED: + if (updatePackage != null) { + return PackagesPageIcons.ICON_PKG_UPDATE; + } else { + return PackagesPageIcons.ICON_PKG_INSTALLED; + } + case NEW: + return PackagesPageIcons.ICON_PKG_NEW; + case DELETED: + return PackagesPageIcons.ICON_PKG_INCOMPAT; + } + } + return VOID; + } + + + /** + * Returns the text for the label of the given element. + * @param element Target + * @param columnIndex The index of the column being displayed + * @return the text string used to label the element, or VOID if there is no text label for the given object + */ + @Override + public String getText(Object element, int columnIndex) { + switch (columnIndex) + { + case PackagesPage.NAME: + return getPkgItemName(); + case PackagesPage.API: + { + AndroidVersion version = getAndroidVersion(); + return version == null ? VOID : getAndroidVersion().getApiString(); + } + case PackagesPage.REVISION: + // Do not repeat version if included in name + if (Pattern.matches(".*\\d+\\.\\d+\\.\\d+.*", getPkgItemName())) + return VOID; + return mainPackage.getVersion().toString(); + case PackagesPage.STATUS: + return getStatusText(); + default: + } + return VOID; + } + + /** + * Get the text displayed in the tool tip for given element + * @param element Target + * @return the tooltop text, or VOID for no text to display + */ + @Override + public String getToolTipText(Object element) { + String s = getTooltipDescription(mainPackage); + + if ((updatePackage != null) && updatePackage.isUpdate()) { + s += "\n-----------------" + //$NON-NLS-1$ + "\nUpdate Available:\n" + //$NON-NLS-1$ + getTooltipDescription(updatePackage.getRemote()); + } + return s; + } + + /** + * Mark item as checked according to given criteria. Force uncheck if no criteria specified. + * @param selectUpdates If true, select all update packages + * @param topApiLevel If greater than 0, select platform packages of this api level + */ + @Override + public void checkSelections( + boolean selectUpdates, + int topApiLevel) + { + boolean hasUpdate = (state == PkgState.INSTALLED) && (updatePackage != null); + if (selectUpdates && hasUpdate) { + setChecked(true); + return; + } + if (topApiLevel > 0) { + if (hasUpdate || // or new packages excluding system images and previews + ((state == PkgState.NEW) && (metaPackage.getPackageType() != PackageType.system_images))) { + AndroidVersion version = getAndroidVersion(); + if ((version != null) && (version.getApiLevel() == topApiLevel) && !version.isPreview()) { + setChecked(true); + return; + } + } + } else { + setChecked(false); + } + } + + @Override + public void markDeleted() + { + state = PkgState.DELETED; + setChecked(false); + updatePackage = null; + } + + @Override + public boolean isDeleted() + { + return state == PkgState.DELETED; + } + + /** Returns a string representation of this item, useful when debugging. */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('<'); + + if (isChecked) { + sb.append(" * "); //$NON-NLS-1$ + } + + sb.append(state.toString()); + + if (mainPackage != null) { + sb.append(", pkg:"); //$NON-NLS-1$ + sb.append(mainPackage.toString()); + } + + if (updatePackage != null) { + sb.append(", updated by:"); //$NON-NLS-1$ + sb.append(updatePackage.toString()); + } + + sb.append('>'); + return sb.toString(); + } + + @Override + public int compareTo(PkgItem other) { + if (other == null) + return Integer.MIN_VALUE; + int comparison1 = state.ordinal() - other.getState().ordinal(); + if (comparison1 != 0) + return comparison1; + if (hasUpdatePkg() && other.hasUpdatePkg()) + return updatePackage.compareTo(other.getUpdatePkg()); + return mainPackage.compareTo(other.getMainPackage()); + } + + /** + * Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package + * and update package must be the similar. + */ + @Override + public boolean equals(Object obj) { + return (obj instanceof PkgItem) && (compareTo((PkgItem) obj) == 0); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + state.hashCode(); + result = prime * result + mainPackage.hashCode(); + result = prime * result + ((updatePackage == null) ? 0 : updatePackage.hashCode()); + return result; + } + + @Nullable + public static AndroidVersion getAndroidVersion(RepoPackage repoPackage) { + TypeDetails details = repoPackage.getTypeDetails(); + if (details instanceof DetailsTypes.ApiDetailsType) { + return ((DetailsTypes.ApiDetailsType)details).getAndroidVersion(); + } + return null; + } + + public static boolean isPreview(RepoPackage repoPackage) { + TypeDetails details = repoPackage.getTypeDetails(); + if (details instanceof DetailsTypes.ApiDetailsType) { + return ((DetailsTypes.ApiDetailsType)details).getCodename() != null; + } + return false; + } + + private String getStatusText() { + switch(state) { + case INSTALLED: + if (updatePackage != null) { + return String.format( + "Update available: rev. %1$s", + updatePackage.getRemote().getVersion().toString()); + } + return "Installed"; + + case NEW: + if (((RemotePackage)mainPackage).getArchive().isCompatible()) { + return "Not installed"; + } else { + return String.format("Not compatible with %1$s", + SdkConstants.currentPlatformName()); + } + case DELETED: + return "Deleted"; + } + return state.toString(); + } + + private String getTooltipDescription(RepoPackage repoPackage) { + String s = repoPackage.getDisplayName(); + if (repoPackage instanceof RemotePackage) { + RemotePackage remote = (RemotePackage) repoPackage; + // For non-installed item get download size + long fileSize = remote.getArchive().getComplete().getSize(); + s += '\n' + Utilities.formatFileSize(fileSize); + s += String.format("\nProvided by %1$s", remote.getSource().getUrl()); + } + return s; + } + + private String getPkgItemName() { + if (metaPackage.getPackageType() == PackageType.platforms) + return "Platform SDK"; + return mainPackage.getDisplayName(); + } + + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgTreeColumnViewerLabelProvider.java similarity index 94% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgTreeColumnViewerLabelProvider.java index 575b8a3e..30791d88 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/PkgTreeColumnViewerLabelProvider.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.repository.ui; +package com.android.sdkuilib.internal.repository.content; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.ColumnLabelProvider; @@ -39,8 +39,7 @@ * delegate all the tooltip calls for completeness and avoid surprises later * if we ever decide to override more things in the label provider. */ -class PkgTreeColumnViewerLabelProvider extends TreeColumnViewerLabelProvider { - +public class PkgTreeColumnViewerLabelProvider extends TreeColumnViewerLabelProvider { private CellLabelProvider mTooltipProvider; public PkgTreeColumnViewerLabelProvider(ColumnLabelProvider columnLabelProvider) { @@ -134,4 +133,5 @@ public int getToolTipStyle(Object object) { } return super.getToolTipStyle(object); } + } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOp.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOp.java new file mode 100644 index 00000000..034f3e63 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOp.java @@ -0,0 +1,84 @@ +package com.android.sdkuilib.internal.repository.content; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.android.repository.api.RepoPackage; + +/** + * An update operation, customized to either sort by API or sort by source. + */ +public abstract class UpdateOp { + static public class SdkSource{} + + private final List> mCategories = new ArrayList<>(); + private final Set> mCatsToRemove = new HashSet<>(); + private final Set mItemsToRemove = new HashSet<>(); + private final Map mUpdatesToRemove = new HashMap<>(); + + /** Removes all internal state. */ + public void clear() { + } + + /** Retrieve the sorted category list. */ + public List> getCategories() { + return mCategories; + } + + /** Retrieve the category key type for the given package */ + public abstract CategoryKeyType getCategoryKeyType(RepoPackage pkg); + + /** Retrieve the category key value for the given package. May be null. */ + public abstract K getCategoryKeyValue(RepoPackage pkg); + + /** Modified {@code currentCategories} to add default categories. */ + public abstract void addDefaultCategories(); + + /** Creates the category for the given key and returns it. */ + public abstract PkgCategory createCategory(CategoryKeyType catKeyType, K catKeyValue); + + /** Sorts the category list (but not the items within the categories.) */ + public abstract void sortCategoryList(); + + /** Called after items of a given category have changed. Used to sort the + * items and/or adjust the category name. */ + public abstract void postCategoryItemsChanged(); + + public void updateStart() { + } + + public boolean updateSourcePackages(SdkSource source, RepoPackage[] newPackages) { + return false; + } + + public boolean updateEnd() { + return false; + } + public boolean isKeep(PkgItem item) { + return !mItemsToRemove.contains(item); + } + + public void keep(Package pkg) { + mUpdatesToRemove.remove(pkg); + } + + public void keep(PkgItem item) { + mItemsToRemove.remove(item); + } + + public void keep(PkgCategory cat) { + mCatsToRemove.remove(cat); + } + + public void dontKeep(PkgItem item) { + mItemsToRemove.add(item); + } + + public void dontKeep(PkgCategory cat) { + mCatsToRemove.add(cat); + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOpApi.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOpApi.java new file mode 100644 index 00000000..7ae38daf --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/content/UpdateOpApi.java @@ -0,0 +1,110 @@ +package com.android.sdkuilib.internal.repository.content; + +import java.util.Collections; +import java.util.Comparator; + +import com.android.repository.api.RepoPackage; +import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; +import com.android.sdklib.AndroidVersion; + +public class UpdateOpApi extends UpdateOp { + + @Override + public CategoryKeyType getCategoryKeyType(RepoPackage pkg) { + // Sort by API + AndroidVersion androidVersion = PkgItem.getAndroidVersion(pkg); + if (androidVersion != null) { + return CategoryKeyType.API; + + } else if (pkg.getPath().indexOf("tools") != -1) { + if (PkgItem.isPreview(pkg)) { + return CategoryKeyType.TOOLS_PREVIEW; + } else { + return CategoryKeyType.TOOLS; + } + } else { + return CategoryKeyType.EXTRA; + } + } + + @Override + public AndroidVersion getCategoryKeyValue(RepoPackage pkg) { + // Sort by API + return PkgItem.getAndroidVersion(pkg); + } + + @Override + public void addDefaultCategories() { + // TODO Auto-generated method stub + + } + + @Override + public PkgCategory createCategory(CategoryKeyType catKeyType, AndroidVersion catKeyValue) { + // Create API category. + PkgCategory cat = null; + + // We should not be trying to recreate the tools or extra categories. + //assert (catKeyType != CategoryKeyType.TOOLS) && (catKeyType != CategoryKeyType.EXTRA); + cat = new PkgCategoryApi( + catKeyType, + catKeyValue, + PackagesPageIcons.ICON_CAT_PLATFORM); + + return cat; + } + + @Override + public void sortCategoryList() { + // Sort the categories list. + // We always want categories in order tools..platforms..extras. + // For platform, we compare in descending order (o2-o1). + // This order is achieved by having the category keys ordered as + // needed for the sort to just do what we expect. + + synchronized (getCategories()) { + Collections.sort(getCategories(), new Comparator>() { + @Override + public int compare(PkgCategory cat1, PkgCategory cat2) { + int comparison1 = cat1.getKeyType().ordinal() - cat2.getKeyType().ordinal(); + if ((cat1.getKeyType() == CategoryKeyType.API) && (cat2.getKeyType() == CategoryKeyType.API)) + return cat2.getKeyValue().compareTo(cat1.getKeyValue()); + else + return comparison1; + } + }); + for (PkgCategory cat: getCategories()) + sortPackages(cat); + } + } + + @Override + public void postCategoryItemsChanged() { + // TODO Auto-generated method stub + + } + + private void sortPackages(PkgCategory cat) + { + synchronized (cat) + { + Collections.sort(cat.getItems(), new Comparator() { + + @Override + public int compare(PkgItem item1, PkgItem item2) { + int ordinal1 = item1.getMetaPackage().getPackageType().ordinal(); + int ordinal2 = item2.getMetaPackage().getPackageType().ordinal(); + int comparison1 = ordinal1 - ordinal2; + if (comparison1 != 0) + return comparison1; + String name1 = PackageAnalyser.getNameFromPath(item1.getMainPackage().getPath()); + String name2 = PackageAnalyser.getNameFromPath(item2.getMainPackage().getPath()); + int comparison2 = name1.compareTo(name2); + // Use reverse lexical order of paths for same package types to get top down version ordering + return comparison2 != 0 ? comparison2 : item2.getMainPackage().getPath().compareTo(item1.getMainPackage().getPath()); + } + + }); + } + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java deleted file mode 100644 index 5617898e..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Copyright (C) 2011 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.sdkuilib.internal.repository.core; - -import com.android.SdkConstants; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.repository.packages.BuildToolPackage; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.IFullRevisionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.updater.PkgItem; -import com.android.sdklib.internal.repository.updater.PkgItem.PkgState; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.FullRevision.PreviewComparison; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; -import com.android.utils.Pair; -import com.android.utils.SparseArray; -import com.google.common.collect.Maps; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Helper class that separates the logic of package management from the UI - * so that we can test it using head-less unit tests. - */ -public class PackagesDiffLogic { - private final SwtUpdaterData mUpdaterData; - private boolean mFirstLoadComplete = true; - - public PackagesDiffLogic(SwtUpdaterData swtUpdaterData) { - mUpdaterData = swtUpdaterData; - } - - /** - * Removes all the internal state and resets the object. - * Useful for testing. - */ - public void clear() { - mFirstLoadComplete = true; - mOpApi.clear(); - } - - /** Return mFirstLoadComplete and resets it to false. - * All following calls will returns false. */ - public boolean isFirstLoadComplete() { - boolean b = mFirstLoadComplete; - mFirstLoadComplete = false; - return b; - } - - /** - * Mark all new and update PkgItems as checked. - * - * @param selectNew If true, select all new packages (except the rc/preview ones). - * @param selectUpdates If true, select all update packages. - * @param selectTop If true, select the top platform. - * If the top platform has nothing installed, select all items in it (except the rc/preview); - * If it is partially installed, at least select the platform and system images if none of - * the system images are installed. - * @param currentPlatform The {@link SdkConstants#currentPlatform()} value. - */ - public void checkNewUpdateItems( - boolean selectNew, - boolean selectUpdates, - boolean selectTop, - int currentPlatform) { - int maxApi = 0; - Set installedPlatforms = new HashSet(); - SparseArray> platformItems = new SparseArray>(); - - boolean hasTools = false; - Map, Pair> toolsCandidates = Maps.newHashMap(); - toolsCandidates.put(PlatformToolPackage.class, Pair.of((PkgItem)null, (FullRevision)null)); - toolsCandidates.put(BuildToolPackage.class, Pair.of((PkgItem)null, (FullRevision)null)); - - // sort items in platforms... directly deal with new/update items - List allItems = getAllPkgItems(); - for (PkgItem item : allItems) { - if (!item.hasCompatibleArchive()) { - // Ignore items that have no archive compatible with the current platform. - continue; - } - - // Get the main package's API level. We don't need to look at the updates - // since by definition they should target the same API level. - int api = 0; - Package p = item.getMainPackage(); - if (p instanceof IAndroidVersionProvider) { - api = ((IAndroidVersionProvider) p).getAndroidVersion().getApiLevel(); - } - - if (selectTop && api > 0) { - // Keep track of the max api seen - maxApi = Math.max(maxApi, api); - - // keep track of what platform is currently installed (that is, has at least - // one thing installed.) - if (item.getState() == PkgState.INSTALLED) { - installedPlatforms.add(api); - } - - // for each platform, collect all its related item for later use below. - List items = platformItems.get(api); - if (items == null) { - platformItems.put(api, items = new ArrayList()); - } - items.add(item); - } - - if ((selectUpdates || selectNew) && - item.getState() == PkgState.NEW && - !item.getRevision().isPreview()) { - boolean sameFound = false; - Package newPkg = item.getMainPackage(); - if (newPkg instanceof IFullRevisionProvider) { - // We have a potential new non-preview package; but this kind of package - // supports having previews, which means we want to make sure we're not - // offering an older "new" non-preview if there's a newer preview installed. - // - // We should get into this odd situation only when updating an RC/preview - // by a final release pkg. - - IFullRevisionProvider newPkg2 = (IFullRevisionProvider) newPkg; - for (PkgItem item2 : allItems) { - if (item2.getState() == PkgState.INSTALLED) { - Package installed = item2.getMainPackage(); - - if (installed.getRevision().isPreview() && - newPkg2.sameItemAs(installed, PreviewComparison.IGNORE)) { - sameFound = true; - - if (installed.canBeUpdatedBy(newPkg) == UpdateInfo.UPDATE) { - item.setChecked(true); - break; - } - } - } - } - } - - if (selectNew && !sameFound) { - item.setChecked(true); - } - - } else if (selectUpdates && item.hasUpdatePkg()) { - item.setChecked(true); - } - - // Keep track of the tools and offer to auto-select platform-tools/build-tools. - if (selectTop) { - if (p instanceof ToolPackage && p.isLocal()) { - hasTools = true; // main tool package is installed. - } else if (p instanceof PlatformToolPackage || p instanceof BuildToolPackage) { - for (Class clazz : toolsCandidates.keySet()) { - if (clazz.isInstance(p)) { // allow p to be a mock-derived class - if (p.isLocal()) { - // There's one such package installed, we don't need candidates. - toolsCandidates.remove(clazz); - } else if (toolsCandidates.containsKey(clazz)) { - Pair val = toolsCandidates.get(clazz); - FullRevision rev = p.getRevision(); - if (!rev.isPreview()) { - // Don't auto-select previews. - if (val.getSecond() == null || - rev.compareTo(val.getSecond()) > 0) { - // No revision: set the first candidate. - // Or we found a new higher revision - toolsCandidates.put(clazz, Pair.of(item, rev)); - } - } - } - break; - } - } - } - } - } - - // Select the top platform/build-tool found above if needed. - if (selectTop && hasTools) { - for (Pair candidate : toolsCandidates.values()) { - PkgItem item = candidate.getFirst(); - if (item != null) { - item.setChecked(true); - } - } - } - - - // Select top platform items. - - List items = platformItems.get(maxApi); - if (selectTop && maxApi > 0 && items != null) { - if (!installedPlatforms.contains(maxApi)) { - // If the top platform has nothing installed at all, select everything in it - for (PkgItem item : items) { - if ((item.getState() == PkgState.NEW && !item.getRevision().isPreview()) || - item.hasUpdatePkg()) { - item.setChecked(true); - } - } - - } else { - // The top platform has at least one thing installed. - - // First make sure the platform package itself is installed, or select it. - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage && - item.getState() == PkgState.NEW && !item.getRevision().isPreview()) { - item.setChecked(true); - break; - } - } - - // Check we have at least one system image installed, otherwise select them - boolean hasSysImg = false; - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage && item.getState() == PkgState.INSTALLED) { - if (item.hasUpdatePkg() && item.isChecked()) { - // If the installed platform is scheduled for update, look for the - // system image in the update package, not the current one. - p = item.getUpdatePkg(); - if (p instanceof PlatformPackage) { - hasSysImg = ((PlatformPackage) p).getIncludedAbi() != null; - } - } else { - // Otherwise look into the currently installed platform - hasSysImg = ((PlatformPackage) p).getIncludedAbi() != null; - } - if (hasSysImg) { - break; - } - } - if (p instanceof SystemImagePackage && - ((SystemImagePackage) p).isPlatform() && - item.getState() == PkgState.INSTALLED) { - hasSysImg = true; - break; - } - } - if (!hasSysImg) { - // No system image installed. - // Try whether the current platform or its update would bring one. - - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage) { - if (item.getState() == PkgState.NEW && - !item.getRevision().isPreview() && - ((PlatformPackage) p).getIncludedAbi() != null) { - item.setChecked(true); - hasSysImg = true; - } else if (item.hasUpdatePkg()) { - p = item.getUpdatePkg(); - if (p instanceof PlatformPackage && - ((PlatformPackage) p).getIncludedAbi() != null) { - item.setChecked(true); - hasSysImg = true; - } - } - } - } - } - if (!hasSysImg) { - // No system image in the platform, try a system image package - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof SystemImagePackage && - ((SystemImagePackage) p).isPlatform() && - item.getState() == PkgState.NEW) { - item.setChecked(true); - } - } - } - } - } - - if (selectTop) { - for (PkgItem item : getAllPkgItems()) { - Package p = item.getMainPackage(); - if (p instanceof ExtraPackage && - item.getState() == PkgState.NEW && - !item.getRevision().isPreview()) { - ExtraPackage ep = (ExtraPackage) p; - - // On Windows, we'll also auto-select the USB driver - if (currentPlatform == SdkConstants.PLATFORM_WINDOWS) { - if (ep.getVendorId().equals("google") && //$NON-NLS-1$ - ep.getPath().equals("usb_driver")) { //$NON-NLS-1$ - item.setChecked(true); - continue; - } - } - - // On all platforms, we'll auto-select the support library. - if (ep.getVendorId().equals("android") && //$NON-NLS-1$ - ep.getPath().equals("support")) { //$NON-NLS-1$ - item.setChecked(true); - continue; - } - - } - } - } - } - - /** - * Mark all PkgItems as not checked. - */ - public void uncheckAllItems() { - for (PkgItem item : getAllPkgItems()) { - item.setChecked(false); - } - } - - /** - * An update operation, customized to either sort by API or sort by source. - */ - abstract class UpdateOp { - private final Set mVisitedSources = new HashSet(); - private final List mCategories = new ArrayList(); - private final Set mCatsToRemove = new HashSet(); - private final Set mItemsToRemove = new HashSet(); - private final Map mUpdatesToRemove = new HashMap(); - - /** Removes all internal state. */ - public void clear() { - mVisitedSources.clear(); - mCategories.clear(); - } - - /** Retrieve the sorted category list. */ - public List getCategories() { - return mCategories; - } - - /** Retrieve the category key for the given package, either local or remote. */ - public abstract Object getCategoryKey(Package pkg); - - /** Modified {@code currentCategories} to add default categories. */ - public abstract void addDefaultCategories(); - - /** Creates the category for the given key and returns it. */ - public abstract PkgCategory createCategory(Object catKey); - /** Adjust attributes of an existing category. */ - public abstract void adjustCategory(PkgCategory cat, Object catKey); - - /** Sorts the category list (but not the items within the categories.) */ - public abstract void sortCategoryList(); - - /** Called after items of a given category have changed. Used to sort the - * items and/or adjust the category name. */ - public abstract void postCategoryItemsChanged(); - - public void updateStart() { - mVisitedSources.clear(); - - // Note that default categories are created after the unused ones so that - // the callback can decide whether they should be marked as unused or not. - mCatsToRemove.clear(); - mItemsToRemove.clear(); - mUpdatesToRemove.clear(); - for (PkgCategory cat : mCategories) { - mCatsToRemove.add(cat); - List items = cat.getItems(); - mItemsToRemove.addAll(items); - for (PkgItem item : items) { - if (item.hasUpdatePkg()) { - mUpdatesToRemove.put(item.getUpdatePkg(), item); - } - } - } - - addDefaultCategories(); - } - - public boolean updateSourcePackages(SdkSource source, Package[] newPackages) { - mVisitedSources.add(source); - if (source == null) { - return processLocals(this, newPackages); - } else { - return processSource(this, source, newPackages); - } - } - - public boolean updateEnd() { - boolean hasChanged = false; - - // Remove unused categories & items at the end of the update - synchronized (mCategories) { - for (PkgCategory unusedCat : mCatsToRemove) { - if (mCategories.remove(unusedCat)) { - hasChanged = true; - } - } - } - - for (PkgCategory cat : mCategories) { - for (Iterator itemIt = cat.getItems().iterator(); itemIt.hasNext(); ) { - PkgItem item = itemIt.next(); - if (mItemsToRemove.contains(item)) { - itemIt.remove(); - hasChanged = true; - } else if (item.hasUpdatePkg() && - mUpdatesToRemove.containsKey(item.getUpdatePkg())) { - item.removeUpdate(); - hasChanged = true; - } - } - } - - mCatsToRemove.clear(); - mItemsToRemove.clear(); - mUpdatesToRemove.clear(); - - return hasChanged; - } - - public boolean isKeep(PkgItem item) { - return !mItemsToRemove.contains(item); - } - - public void keep(Package pkg) { - mUpdatesToRemove.remove(pkg); - } - - public void keep(PkgItem item) { - mItemsToRemove.remove(item); - } - - public void keep(PkgCategory cat) { - mCatsToRemove.remove(cat); - } - - public void dontKeep(PkgItem item) { - mItemsToRemove.add(item); - } - - public void dontKeep(PkgCategory cat) { - mCatsToRemove.add(cat); - } - } - - private final UpdateOpApi mOpApi = new UpdateOpApi(); - - public List getCategories() { - return mOpApi.getCategories(); - } - - public List getAllPkgItems() { - List items = new ArrayList(); - - List cats = getCategories(); - synchronized (cats) { - for (PkgCategory cat : cats) { - items.addAll(cat.getItems()); - } - } - - return items; - } - - public void updateStart() { - mOpApi.updateStart(); - } - - public boolean updateSourcePackages(SdkSource source, Package[] newPackages) { - - return mOpApi.updateSourcePackages(source, newPackages); - } - - public boolean updateEnd() { - return mOpApi.updateEnd(); - } - - - /** Process all local packages. Returns true if something changed. */ - private boolean processLocals(UpdateOp op, Package[] packages) { - boolean hasChanged = false; - List cats = op.getCategories(); - Set keep = new HashSet(); - - // For all locally installed packages, check they are either listed - // as installed or create new installed items for them. - - nextPkg: for (Package localPkg : packages) { - // Check to see if we already have the exact same package - // (type & revision) marked as installed. - for (PkgCategory cat : cats) { - for (PkgItem currItem : cat.getItems()) { - if (currItem.getState() == PkgState.INSTALLED && - currItem.isSameMainPackageAs(localPkg)) { - // This package is already listed as installed. - op.keep(currItem); - op.keep(cat); - keep.add(currItem); - continue nextPkg; - } - } - } - - // If not found, create a new installed package item - keep.add(addNewItem(op, localPkg, PkgState.INSTALLED)); - hasChanged = true; - } - - // Remove installed items that we don't want to keep anymore. They would normally be - // cleanup up in UpdateOp.updateEnd(); however it's easier to remove them before we - // run processSource() to avoid merging updates in items that would be removed later. - - for (PkgCategory cat : cats) { - for (Iterator itemIt = cat.getItems().iterator(); itemIt.hasNext(); ) { - PkgItem item = itemIt.next(); - if (item.getState() == PkgState.INSTALLED && !keep.contains(item)) { - itemIt.remove(); - hasChanged = true; - } - } - } - - if (hasChanged) { - op.postCategoryItemsChanged(); - } - - return hasChanged; - } - - /** - * {@link PkgState}s to check in {@link #processSource(UpdateOp, SdkSource, Package[])}. - * The order matters. - * When installing the diff will have both the new and the installed item and we - * need to merge with the installed one before the new one. - */ - private final static PkgState[] PKG_STATES = { PkgState.INSTALLED, PkgState.NEW }; - - /** Process all remote packages. Returns true if something changed. */ - private boolean processSource(UpdateOp op, SdkSource source, Package[] packages) { - boolean hasChanged = false; - List cats = op.getCategories(); - - boolean enablePreviews = - mUpdaterData.getSettingsController().getSettings().getEnablePreviews(); - - nextPkg: for (Package newPkg : packages) { - - if (!enablePreviews && newPkg.getRevision().isPreview()) { - // This is a preview and previews are not enabled. Ignore the package. - // Starting with Tools 23, we explicitly allows Build-Tools RC packages to - // always be visible so only RCs for Tools & Platform-Tools will be hidden. - if (!(newPkg instanceof BuildToolPackage)) { - continue nextPkg; - } - } - - for (PkgCategory cat : cats) { - for (PkgState state : PKG_STATES) { - for (Iterator currItemIt = cat.getItems().iterator(); - currItemIt.hasNext(); ) { - PkgItem currItem = currItemIt.next(); - // We need to merge with installed items first. When installing - // the diff will have both the new and the installed item and we - // need to merge with the installed one before the new one. - if (currItem.getState() != state) { - continue; - } - // Only process current items if they represent the same item (but - // with a different revision number) than the new package. - Package mainPkg = currItem.getMainPackage(); - if (!mainPkg.sameItemAs(newPkg)) { - continue; - } - - // Check to see if we already have the exact same package - // (type & revision) marked as main or update package. - if (currItem.isSameMainPackageAs(newPkg)) { - op.keep(currItem); - op.keep(cat); - continue nextPkg; - } else if (currItem.hasUpdatePkg() && - currItem.isSameUpdatePackageAs(newPkg)) { - op.keep(currItem.getUpdatePkg()); - op.keep(cat); - continue nextPkg; - } - - switch (currItem.getState()) { - case NEW: - if (newPkg.getRevision().compareTo(mainPkg.getRevision()) < 0) { - if (!op.isKeep(currItem)) { - // The new item has a lower revision than the current one, - // but the current one hasn't been marked as being kept so - // it's ok to downgrade it. - currItemIt.remove(); - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - } else if (newPkg.getRevision().compareTo(mainPkg.getRevision()) > 0) { - // We have a more recent new version, remove the current one - // and replace by a new one - currItemIt.remove(); - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - break; - case INSTALLED: - // if newPkg.revision<=mainPkg.revision: it's already installed, ignore. - if (newPkg.getRevision().compareTo(mainPkg.getRevision()) > 0) { - // This is a new update for the main package. - if (currItem.mergeUpdate(newPkg)) { - op.keep(currItem.getUpdatePkg()); - op.keep(cat); - hasChanged = true; - } - } - break; - } - continue nextPkg; - } - } - } - // If not found, create a new package item - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - - if (hasChanged) { - op.postCategoryItemsChanged(); - } - - return hasChanged; - } - - private PkgItem addNewItem(UpdateOp op, Package pkg, PkgState state) { - List cats = op.getCategories(); - Object catKey = op.getCategoryKey(pkg); - PkgCategory cat = findCurrentCategory(cats, catKey); - - if (cat == null) { - // This is a new category. Create it and add it to the list. - cat = op.createCategory(catKey); - synchronized (cats) { - cats.add(cat); - } - op.sortCategoryList(); - } else { - // Not a new category. Give op a chance to adjust the category attributes - op.adjustCategory(cat, catKey); - } - - PkgItem item = new PkgItem(pkg, state); - op.keep(item); - cat.getItems().add(item); - op.keep(cat); - return item; - } - - private PkgCategory findCurrentCategory( - List currentCategories, - Object categoryKey) { - for (PkgCategory cat : currentCategories) { - if (cat.getKey().equals(categoryKey)) { - return cat; - } - } - return null; - } - - /** - * {@link UpdateOp} describing the Sort-by-API operation. - */ - private class UpdateOpApi extends UpdateOp { - @Override - public Object getCategoryKey(Package pkg) { - // Sort by API - - if (pkg instanceof IAndroidVersionProvider) { - return ((IAndroidVersionProvider) pkg).getAndroidVersion(); - - } else if (pkg instanceof ToolPackage || - pkg instanceof PlatformToolPackage || - pkg instanceof BuildToolPackage) { - if (pkg.getRevision().isPreview()) { - return PkgCategoryApi.KEY_TOOLS_PREVIEW; - } else { - return PkgCategoryApi.KEY_TOOLS; - } - } else { - return PkgCategoryApi.KEY_EXTRA; - } - } - - @Override - public void addDefaultCategories() { - boolean needTools = true; - boolean needExtras = true; - - List cats = getCategories(); - for (PkgCategory cat : cats) { - if (cat.getKey().equals(PkgCategoryApi.KEY_TOOLS)) { - // Mark them as not unused to prevent their removal in updateEnd(). - keep(cat); - needTools = false; - } else if (cat.getKey().equals(PkgCategoryApi.KEY_EXTRA)) { - keep(cat); - needExtras = false; - } - } - - // Always add the tools & extras categories, even if empty (unlikely anyway) - if (needTools) { - PkgCategoryApi acat = new PkgCategoryApi( - PkgCategoryApi.KEY_TOOLS, - null, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_OTHER)); - synchronized (cats) { - cats.add(acat); - } - } - - if (needExtras) { - PkgCategoryApi acat = new PkgCategoryApi( - PkgCategoryApi.KEY_EXTRA, - null, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_OTHER)); - synchronized (cats) { - cats.add(acat); - } - } - } - - @Override - public PkgCategory createCategory(Object catKey) { - // Create API category. - PkgCategory cat = null; - - assert catKey instanceof AndroidVersion; - AndroidVersion key = (AndroidVersion) catKey; - - // We should not be trying to recreate the tools or extra categories. - assert !key.equals(PkgCategoryApi.KEY_TOOLS) && !key.equals(PkgCategoryApi.KEY_EXTRA); - - // We need a label for the category. - // If we have an API level, try to get the info from the SDK Manager. - // If we don't (e.g. when installing a new platform that isn't yet available - // locally in the SDK Manager), it's OK we'll try to find the first platform - // package available. - String platformName = null; - for (IAndroidTarget target : - mUpdaterData.getSdkManager().getTargets()) { - if (target.isPlatform() && key.equals(target.getVersion())) { - platformName = target.getVersionName(); - break; - } - } - - cat = new PkgCategoryApi( - key, - platformName, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_PLATFORM)); - - return cat; - } - - @Override - public void adjustCategory(PkgCategory cat, Object catKey) { - // Pass. Nothing to do for API-sorted categories - } - - @Override - public void sortCategoryList() { - // Sort the categories list. - // We always want categories in order tools..platforms..extras. - // For platform, we compare in descending order (o2-o1). - // This order is achieved by having the category keys ordered as - // needed for the sort to just do what we expect. - - synchronized (getCategories()) { - Collections.sort(getCategories(), new Comparator() { - @Override - public int compare(PkgCategory cat1, PkgCategory cat2) { - assert cat1 instanceof PkgCategoryApi; - assert cat2 instanceof PkgCategoryApi; - assert cat1.getKey() instanceof AndroidVersion; - assert cat2.getKey() instanceof AndroidVersion; - AndroidVersion v1 = (AndroidVersion) cat1.getKey(); - AndroidVersion v2 = (AndroidVersion) cat2.getKey(); - return v2.compareTo(v1); - } - }); - } - } - - @Override - public void postCategoryItemsChanged() { - // Sort the items - for (PkgCategory cat : getCategories()) { - Collections.sort(cat.getItems()); - - // When sorting by API, we can't always get the platform name - // from the package manager. In this case at the very end we - // look for a potential platform package we can use to extract - // the platform version name (e.g. '1.5') from the first suitable - // platform package we can find. - - assert cat instanceof PkgCategoryApi; - PkgCategoryApi pac = (PkgCategoryApi) cat; - if (pac.getPlatformName() == null) { - // Check whether we can get the actual platform version name (e.g. "1.5") - // from the first Platform package we find in this category. - - for (PkgItem item : cat.getItems()) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage) { - String platformName = ((PlatformPackage) p).getVersionName(); - if (platformName != null) { - pac.setPlatformName(platformName); - break; - } - } - } - } - } - - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategory.java deleted file mode 100644 index 7eb57e67..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategory.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2011 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.sdkuilib.internal.repository.core; - - -import com.android.sdklib.internal.repository.updater.PkgItem; - -import java.util.ArrayList; -import java.util.List; - -public abstract class PkgCategory { - private final Object mKey; - private final Object mIconRef; - private final List mItems = new ArrayList(); - private String mLabel; - - public PkgCategory(Object key, String label, Object iconRef) { - mKey = key; - mLabel = label; - mIconRef = iconRef; - } - - public Object getKey() { - return mKey; - } - - public String getLabel() { - return mLabel; - } - - public void setLabel(String label) { - mLabel = label; - } - - public Object getIconRef() { - return mIconRef; - } - - public List getItems() { - return mItems; - } - - @Override - public String toString() { - return String.format("%s ", - this.getClass().getSimpleName(), - mKey == null ? "null" : mKey.toString(), - mLabel, - mItems.size()); - } - - /** {@link PkgCategory}s are equal if their internal keys are equal. */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mKey == null) ? 0 : mKey.hashCode()); - return result; - } - - /** {@link PkgCategory}s are equal if their internal keys are equal. */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - PkgCategory other = (PkgCategory) obj; - if (mKey == null) { - if (other.mKey != null) return false; - } else if (!mKey.equals(other.mKey)) return false; - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java deleted file mode 100644 index 463049ce..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 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.sdkuilib.internal.repository.core; - -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; - - -public class PkgCategorySource extends PkgCategory { - - /** - * A special {@link SdkSource} object that represents the locally installed - * items, or more exactly a lack of remote source. - */ - public final static SdkSource UNKNOWN_SOURCE = - new SdkRepoSource("http://no.source", "Local Packages"); - private final SdkSource mSource; - - /** - * Creates a new {@link PkgCategorySource}. - * This uses {@link SdkSource#toString()} to get the source's description. - * Note that if the name of the source isn't known, the description will use its URL. - */ - public PkgCategorySource(SdkSource source, SwtUpdaterData swtUpdaterData) { - super( - source, // the source is the key and it can be null - source == UNKNOWN_SOURCE ? "Local Packages" : source.toString(), - source == UNKNOWN_SOURCE ? - swtUpdaterData.getImageFactory() - .getImageByName(PackagesPageIcons.ICON_PKG_INSTALLED) : - source); - mSource = source; - } - - @Override - public String toString() { - return String.format("%s ", - this.getClass().getSimpleName(), - mSource.toString(), - getItems().size()); - } - - public SdkSource getSource() { - return mSource; - } - - /** Sets the label to match the source's UI name if the label wasn't already set. */ - public void adjustLabel(SdkSource source) { - if (getLabel() == null || getLabel().startsWith("http")) { //$NON-NLS-1$ - setLabel(source == UNKNOWN_SOURCE ? "Local Packages" : source.toString()); - } - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java deleted file mode 100644 index 34bf17de..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2012 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.sdkuilib.internal.repository.core; - -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.updater.PkgItem; -import com.android.sdklib.repository.IDescription; -import com.android.sdkuilib.internal.repository.ui.PackagesPage; - -import org.eclipse.jface.viewers.IInputProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -import java.util.ArrayList; -import java.util.List; - -/** - * Content provider for the main tree view in {@link PackagesPage}. - */ -public class PkgContentProvider implements ITreeContentProvider { - - private final IInputProvider mViewer; - private boolean mDisplayArchives; - - public PkgContentProvider(IInputProvider viewer) { - mViewer = viewer; - } - - public void setDisplayArchives(boolean displayArchives) { - mDisplayArchives = displayArchives; - } - - @Override - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof ArrayList) { - return ((ArrayList) parentElement).toArray(); - - } else if (parentElement instanceof PkgCategorySource) { - return getSourceChildren((PkgCategorySource) parentElement); - - } else if (parentElement instanceof PkgCategory) { - return ((PkgCategory) parentElement).getItems().toArray(); - - } else if (parentElement instanceof PkgItem) { - if (mDisplayArchives) { - - Package pkg = ((PkgItem) parentElement).getUpdatePkg(); - - // Display update packages as sub-items if the details mode is activated. - if (pkg != null) { - return new Object[] { pkg }; - } - - return ((PkgItem) parentElement).getArchives(); - } - - } else if (parentElement instanceof Package) { - if (mDisplayArchives) { - return ((Package) parentElement).getArchives(); - } - - } - - return new Object[0]; - } - - @Override - @SuppressWarnings("unchecked") - public Object getParent(Object element) { - // This operation is expensive, so we do the minimum - // and don't try to cover all cases. - - if (element instanceof PkgItem) { - Object input = mViewer.getInput(); - if (input != null) { - for (PkgCategory cat : (List) input) { - if (cat.getItems().contains(element)) { - return cat; - } - } - } - } - - return null; - } - - @Override - public boolean hasChildren(Object parentElement) { - if (parentElement instanceof ArrayList) { - return true; - - } else if (parentElement instanceof PkgCategory) { - return true; - - } else if (parentElement instanceof PkgItem) { - if (mDisplayArchives) { - Package pkg = ((PkgItem) parentElement).getUpdatePkg(); - - // Display update packages as sub-items if the details mode is activated. - if (pkg != null) { - return true; - } - - Archive[] archives = ((PkgItem) parentElement).getArchives(); - return archives.length > 0; - } - } else if (parentElement instanceof Package) { - if (mDisplayArchives) { - return ((Package) parentElement).getArchives().length > 0; - } - } - - return false; - } - - @Override - public Object[] getElements(Object inputElement) { - return getChildren(inputElement); - } - - @Override - public void dispose() { - // unused - - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // unused - } - - - private Object[] getSourceChildren(PkgCategorySource parentElement) { - List children = parentElement.getItems(); - - SdkSource source = parentElement.getSource(); - IDescription error = null; - IDescription empty = null; - - String errStr = source.getFetchError(); - if (errStr != null) { - error = new RepoSourceError(source); - } - if (!source.isEnabled() || children.isEmpty()) { - empty = new RepoSourceNotification(source); - } - - if (error != null || empty != null) { - ArrayList children2 = new ArrayList(); - if (error != null) { - children2.add(error); - } - if (empty != null) { - children2.add(empty); - } - children2.addAll(children); - children = children2; - } - - return children.toArray(); - } - - - /** - * A dummy entry returned for sources which had load errors. - * It displays a summary of the error as its short description or - * it displays the source's long description. - */ - public static class RepoSourceError implements IDescription { - - private final SdkSource mSource; - - public RepoSourceError(SdkSource source) { - mSource = source; - } - - @Override - public String getLongDescription() { - return mSource.getLongDescription(); - } - - @Override - public String getShortDescription() { - return mSource.getFetchError(); - } - } - - /** - * A dummy entry returned for sources with no packages. - * We need that to force the SWT tree to display an open/close triangle - * even for empty sources. - */ - public static class RepoSourceNotification implements IDescription { - - private final SdkSource mSource; - - public RepoSourceNotification(SdkSource source) { - mSource = source; - } - - @Override - public String getLongDescription() { - if (mSource.isEnabled()) { - return mSource.getLongDescription(); - } else { - return "Loading from this site has been disabled. " + - "To enable it, use Tools > Manage Add-ons Sites."; - } - } - - @Override - public String getShortDescription() { - if (mSource.isEnabled()) { - return "No packages found."; - } else { - return "This site is disabled. "; - } - } - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java deleted file mode 100644 index cbc33950..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2011 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.sdkuilib.internal.repository.core; - -import com.android.sdkuilib.internal.tasks.ILogUiProvider; -import com.android.utils.ILogger; - - -/** - * Adapter that transform log from an {@link ILogUiProvider} to an {@link ILogger}. - */ -public final class SdkLogAdapter implements ILogUiProvider { - - private ILogger mSdkLog; - private String mLastLogMsg; - - /** - * Creates a new adapter to output log on the given {@code sdkLog}. - * - * @param sdkLog The logger to output to. Must not be null. - */ - public SdkLogAdapter(ILogger sdkLog) { - mSdkLog = sdkLog; - } - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(final String description) { - if (acceptLog(description)) { - mSdkLog.info("%1$s", description); //$NON-NLS-1$ - } - } - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(String log) { - if (acceptLog(log)) { - mSdkLog.info(" %1$s", log); //$NON-NLS-1$ - } - } - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logError(String log) { - if (acceptLog(log)) { - mSdkLog.error(null, " %1$s", log); //$NON-NLS-1$ - } - } - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logVerbose(String log) { - if (acceptLog(log)) { - mSdkLog.verbose(" %1$s", log); //$NON-NLS-1$ - } - } - - // ---- - - /** - * Filter messages displayed in the log:
- * - Messages with a % are typical part of a progress update and shouldn't be in the log.
- * - Messages that are the same as the same output message should be output a second time. - * - * @param msg The potential log line to print. - * @return True if the log line should be printed, false otherwise. - */ - private boolean acceptLog(String msg) { - if (msg == null) { - return false; - } - - msg = msg.trim(); - if (msg.indexOf('%') != -1) { - return false; - } - - if (msg.equals(mLastLogMsg)) { - return false; - } - - mLastLogMsg = msg; - return true; - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SwtPackageLoader.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SwtPackageLoader.java deleted file mode 100644 index d5e7982c..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/core/SwtPackageLoader.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 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.sdkuilib.internal.repository.core; - -import com.android.annotations.NonNull; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.updater.PackageLoader; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -/** - * Loads packages fetched from the remote SDK Repository and keeps track - * of their state compared with the current local SDK installation. - */ -public class SwtPackageLoader extends PackageLoader { - - /** - * Creates a new PackageManager associated with the given {@link SwtUpdaterData} - * and using the {@link SwtUpdaterData}'s default {@link DownloadCache}. - * - * @param swtUpdaterData The {@link SwtUpdaterData}. Must not be null. - */ - public SwtPackageLoader(SwtUpdaterData swtUpdaterData) { - super(swtUpdaterData); - } - - /** - * Creates a new PackageManager associated with the given {@link SwtUpdaterData} - * but using the specified {@link DownloadCache} instead of the one from - * {@link SwtUpdaterData}. - * - * @param swtUpdaterData The {@link SwtUpdaterData}. Must not be null. - * @param cache The {@link DownloadCache} to use instead of the one from {@link SwtUpdaterData}. - */ - public SwtPackageLoader(SwtUpdaterData swtUpdaterData, DownloadCache cache) { - super(swtUpdaterData, cache); - } - - /** - * Runs the runnable on the UI thread using {@link Display#syncExec(Runnable)}. - * - * @param r Non-null runnable. - */ - @Override - protected void runOnUiThread(@NonNull Runnable r) { - SwtUpdaterData swtUpdaterData = (SwtUpdaterData) getUpdaterData(); - Shell shell = swtUpdaterData.getWindowShell(); - - if (shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(r); - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/ImageFactory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/ImageFactory.java deleted file mode 100644 index d985162f..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/icons/ImageFactory.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2009 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.sdkuilib.internal.repository.icons; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; - -import org.eclipse.swt.SWTException; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; - - -/** - * An utility class to serve {@link Image} correspond to the various icons - * present in this package and dispose of them correctly at the end. - */ -public class ImageFactory { - - private final Display mDisplay; - private final Map mImages = new HashMap(); - - /** - * Filter an image when it's loaded by - * {@link ImageFactory#getImageByName(String, String, Filter)}. - */ - public interface Filter { - /** - * Invoked by {@link ImageFactory#getImageByName(String, String, Filter)} when - * a non-null {@link Image} object has been loaded. The filter should create a - * new image, modifying it as needed.
- * If no modification is necessary, the filter can simply return the source image.
- * The result will be cached and returned by {@link ImageFactory}. - *

- * - * @param source A non-null source image. - * @return Either the source or a new, potentially modified, image. - */ - @NonNull public Image filter(@NonNull Image source); - } - - public ImageFactory(@NonNull Display display) { - mDisplay = display; - } - - /** - * Loads an image given its filename (with its extension). - * Might return null if the image cannot be loaded.
- * The image is cached. Successive calls will return the same object.
- * The image is automatically disposed when {@link ImageFactory} is disposed. - * - * @param imageName The filename (with extension) of the image to load. - * @return A new or existing {@link Image}. The caller must NOT dispose the image (the - * image will disposed by {@link #dispose()}). The returned image can be null if the - * expected file is missing. - */ - @Nullable - public Image getImageByName(@NonNull String imageName) { - return getImageByName(imageName, imageName, null); - } - - - /** - * Loads an image given its filename (with its extension), caches it using the given - * {@code KeyName} name and optionally applies a filter to it. - * Might return null if the image cannot be loaded. - * The image is cached. Successive calls using {@code KeyName} will return the same - * object directly (the filter is not re-applied in this case.)
- * The image is automatically disposed when {@link ImageFactory} is disposed. - *

- * - * @param imageName The filename (with extension) of the image to load. - * @return A new or existing {@link Image}. The caller must NOT dispose the image (the - * image will disposed by {@link #dispose()}). The returned image is null if the - * expected file is missing. - */ - @Nullable - public Image getImageByName(@NonNull String imageName, - @NonNull String keyName, - @Nullable Filter filter) { - - Image image = mImages.get(keyName); - if (image != null) { - return image; - } - - InputStream stream = getClass().getResourceAsStream(imageName); - if (stream != null) { - try { - image = new Image(mDisplay, stream); - if (image != null && filter != null) { - Image image2 = filter.filter(image); - if (image2 != image && !image.isDisposed()) { - image.dispose(); - } - image = image2; - } - } catch (SWTException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } - } - - // Store the image in the hash, even if this failed. If it fails now, it will fail later. - mImages.put(keyName, image); - - return image; - } - - /** - * Loads and returns the appropriate image for a given package, archive or source object. - * The image is cached. Successive calls will return the same object. - * - * @param object A {@link SdkSource} or {@link Package} or {@link Archive}. - * @return A new or existing {@link Image}. The caller must NOT dispose the image (the - * image will disposed by {@link #dispose()}). The returned image can be null if the - * object is of an unknown type. - */ - @Nullable - public Image getImageForObject(@Nullable Object object) { - - if (object == null) { - return null; - } - - if (object instanceof Image) { - return (Image) object; - } - - String clz = object.getClass().getSimpleName(); - if (clz.endsWith(Package.class.getSimpleName())) { - String name = clz.replaceFirst(Package.class.getSimpleName(), "") //$NON-NLS-1$ - .replace("SystemImage", "sysimg") //$NON-NLS-1$ //$NON-NLS-2$ - .toLowerCase(Locale.US); - name += "_pkg_16.png"; //$NON-NLS-1$ - return getImageByName(name); - } - - if (object instanceof PkgContentProvider.RepoSourceError) { - return getImageByName("error_icon_16.png"); //$NON-NLS-1$ - - } else if (object instanceof PkgContentProvider.RepoSourceNotification) { - return getImageByName("nopkg_icon_16.png"); //$NON-NLS-1$ - } - - if (object instanceof Archive) { - if (((Archive) object).isCompatible()) { - return getImageByName("archive_icon16.png"); //$NON-NLS-1$ - } else { - return getImageByName("incompat_icon16.png"); //$NON-NLS-1$ - } - } - - if (object instanceof String) { - return getImageByName((String) object); - } - - - if (object != null) { - // For debugging - // System.out.println("No image for object " + object.getClass().getSimpleName()); - } - - return null; - } - - /** - * Dispose all the images created by this factory so far. - */ - public void dispose() { - Iterator it = mImages.values().iterator(); - while(it.hasNext()) { - Image img = it.next(); - if (img != null && img.isDisposed() == false) { - img.dispose(); - } - it.remove(); - } - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java deleted file mode 100644 index 01539496..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2011 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.sdkuilib.internal.repository.ui; - -import com.android.sdklib.internal.repository.sources.SdkAddonSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSourceProperties; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.internal.repository.sources.SdkSysImgSource; -import com.android.sdklib.repository.SdkSysImgConstants; -import com.android.sdkuilib.internal.repository.UpdaterBaseDialog; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -import org.eclipse.jface.dialogs.IInputValidator; -import org.eclipse.jface.dialogs.InputDialog; -import org.eclipse.jface.viewers.CheckStateChangedEvent; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ICheckStateListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.TabFolder; -import org.eclipse.swt.widgets.TabItem; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Dialog that displays 2 tabs:
- * - one tab with the list of extra add-ons sites defined by the user.
- * - one tab with the list of 3rd-party add-ons currently available, which the user can - * deactivate to prevent from loading them. - */ -public class AddonSitesDialog extends UpdaterBaseDialog { - - private final SdkSources mSources; - private Table mUserTable; - private TableViewer mUserTableViewer; - private CheckboxTableViewer mSitesTableViewer; - private Button mUserButtonNew; - private Button mUserButtonDelete; - private Button mUserButtonEdit; - private Runnable mSourcesChangeListener; - - /** - * Create the dialog. - * - * @param parent The parent's shell - * @wbp.parser.entryPoint - */ - public AddonSitesDialog(Shell parent, SwtUpdaterData updaterData) { - super(parent, updaterData, "Add-on Sites"); - mSources = updaterData.getSources(); - assert mSources != null; - } - - /** - * Create contents of the dialog. - * @wbp.parser.entryPoint - */ - @Override - protected void createContents() { - super.createContents(); - Shell shell = getShell(); - shell.setMinimumSize(new Point(300, 300)); - shell.setSize(600, 400); - - TabFolder tabFolder = new TabFolder(shell, SWT.NONE); - GridDataBuilder.create(tabFolder).fill().grab().hSpan(2); - - TabItem sitesTabItem = new TabItem(tabFolder, SWT.NONE); - sitesTabItem.setText("Official Add-on Sites"); - createTabOfficialSites(tabFolder, sitesTabItem); - - TabItem userTabItem = new TabItem(tabFolder, SWT.NONE); - userTabItem.setText("User Defined Sites"); - createTabUserSites(tabFolder, userTabItem); - - // placeholder for aligning close button - Label label = new Label(shell, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab(); - - createCloseButton(); - } - - void createTabOfficialSites(TabFolder tabFolder, TabItem sitesTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - sitesTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(3); - - Label label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hGrab().vCenter().hSpan(3); - label.setText( - "This lets select which official 3rd-party sites you want to load.\n" + - "\n" + - "These sites are managed by non-Android vendors to provide add-ons and extra packages.\n" + - "They are by default all enabled. When you disable one, the SDK Manager will not check the site for new packages." - ); - - mSitesTableViewer = CheckboxTableViewer.newCheckList(root, SWT.BORDER | SWT.FULL_SELECTION); - mSitesTableViewer.setContentProvider(new SourcesContentProvider()); - - Table sitesTable = mSitesTableViewer.getTable(); - sitesTable.setToolTipText("Enable 3rd-Party Site"); - sitesTable.setLinesVisible(true); - sitesTable.setHeaderVisible(true); - GridDataBuilder.create(sitesTable).fill().grab().hSpan(3); - - TableViewerColumn columnViewer = new TableViewerColumn(mSitesTableViewer, SWT.NONE); - TableColumn column = columnViewer.getColumn(); - column.setResizable(true); - column.setWidth(150); - column.setText("Name"); - columnViewer.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - if (element instanceof SdkSource) { - String name = ((SdkSource) element).getUiName(); - if (name != null) { - return name; - } - return ((SdkSource) element).getShortDescription(); - } - return super.getText(element); - } - }); - - columnViewer = new TableViewerColumn(mSitesTableViewer, SWT.NONE); - column = columnViewer.getColumn(); - column.setResizable(true); - column.setWidth(400); - column.setText("URL"); - columnViewer.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - if (element instanceof SdkSource) { - return ((SdkSource) element).getUrl(); - } - return super.getText(element); - } - }); - - mSitesTableViewer.addCheckStateListener(new ICheckStateListener() { - @Override - public void checkStateChanged(CheckStateChangedEvent event) { - on_SitesTableViewer_checkStateChanged(event); - } - }); - - // "enable all" and "disable all" buttons under the table - Button selectAll = new Button(root, SWT.NONE); - selectAll.setText("Enable All"); - GridDataBuilder.create(selectAll).hLeft(); - selectAll.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - on_SitesTableViewer_selectAll(); - } - }); - - // placeholder between both buttons - label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab(); - - Button deselectAll = new Button(root, SWT.NONE); - deselectAll.setText("Disable All"); - GridDataBuilder.create(deselectAll).hRight(); - deselectAll.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - on_SitesTableViewer_deselectAll(); - } - }); - } - - void createTabUserSites(TabFolder tabFolder, TabItem userTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - userTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(2); - - Label label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hLeft().vCenter().hSpan(2); - label.setText( - "This lets you manage a list of user-contributed external add-on sites URLs.\n" + - "\n" + - "Add-on sites can provide new add-ons and extra packages.\n" + - "They cannot provide standard Android platforms, system images or docs.\n" + - "Adding a URL here will not allow you to clone an official Android repository." - ); - - mUserTableViewer = new TableViewer(root, SWT.BORDER | SWT.FULL_SELECTION); - mUserTableViewer.setContentProvider(new SourcesContentProvider()); - - mUserTableViewer.addPostSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - on_UserTableViewer_selectionChanged(event); - } - }); - mUserTable = mUserTableViewer.getTable(); - mUserTable.setLinesVisible(true); - mUserTable.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent event) { - on_UserTable_mouseUp(event); - } - }); - GridDataBuilder.create(mUserTable).fill().grab().vSpan(5); - - TableViewerColumn tableViewerColumn = new TableViewerColumn(mUserTableViewer, SWT.NONE); - TableColumn userColumnUrl = tableViewerColumn.getColumn(); - userColumnUrl.setWidth(100); - - // Implementation detail: set the label provider on the table viewer *after* associating - // a column. This will set the label provider on the column for us. - mUserTableViewer.setLabelProvider(new LabelProvider()); - - - mUserButtonNew = new Button(root, SWT.NONE); - mUserButtonNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - userNewOrEdit(false /*isEdit*/); - } - }); - GridDataBuilder.create(mUserButtonNew).hFill().vCenter(); - mUserButtonNew.setText("New..."); - - mUserButtonEdit = new Button(root, SWT.NONE); - mUserButtonEdit.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - userNewOrEdit(true /*isEdit*/); - } - }); - GridDataBuilder.create(mUserButtonEdit).hFill().vCenter(); - mUserButtonEdit.setText("Edit..."); - - mUserButtonDelete = new Button(root, SWT.NONE); - mUserButtonDelete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - on_UserButtonDelete_widgetSelected(e); - } - }); - GridDataBuilder.create(mUserButtonDelete).hFill().vCenter(); - mUserButtonDelete.setText("Delete..."); - - adjustColumnsWidth(mUserTable, userColumnUrl); - } - - @Override - protected void close() { - if (mSources != null && mSourcesChangeListener != null) { - mSources.removeChangeListener(mSourcesChangeListener); - } - SdkSourceProperties p = new SdkSourceProperties(); - p.save(); - super.close(); - } - - /** - * Adds a listener to adjust the column width when the parent is resized. - */ - private void adjustColumnsWidth(final Table table, final TableColumn column0) { - // 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 * 100 / 100); // 100% - } - }); - } - - private void userNewOrEdit(final boolean isEdit) { - final SdkSource[] knownSources = mSources.getAllSources(); - String title = isEdit ? "Edit Add-on Site URL" : "Add Add-on Site URL"; - String msg = "Please enter the URL of the addon.xml:"; - IStructuredSelection sel = (IStructuredSelection) mUserTableViewer.getSelection(); - final String initialValue = !isEdit || sel.isEmpty() ? null : - sel.getFirstElement().toString(); - - if (isEdit && initialValue == null) { - // Edit with no actual value is not supposed to happen. Ignore this case. - return; - } - - InputDialog dlg = new InputDialog( - getShell(), - title, - msg, - initialValue, - new IInputValidator() { - @Override - public String isValid(String newText) { - - newText = newText == null ? null : newText.trim(); - - if (newText == null || newText.length() == 0) { - return "Error: URL field is empty. Please enter a URL."; - } - - // A URL should have one of the following prefixes - if (!newText.startsWith("file://") && //$NON-NLS-1$ - !newText.startsWith("ftp://") && //$NON-NLS-1$ - !newText.startsWith("http://") && //$NON-NLS-1$ - !newText.startsWith("https://")) { //$NON-NLS-1$ - return "Error: The URL must start by one of file://, ftp://, http:// or https://"; - } - - if (isEdit && newText.equals(initialValue)) { - // Edited value hasn't changed. This isn't an error. - return null; - } - - // Reject URLs that are already in the source list. - // URLs are generally case-insensitive (except for file:// where it all depends - // on the current OS so we'll ignore this case.) - for (SdkSource s : knownSources) { - if (newText.equalsIgnoreCase(s.getUrl())) { - return "Error: This site is already listed."; - } - } - - return null; - } - }); - - if (dlg.open() == Window.OK) { - String url = dlg.getValue().trim(); - - if (!url.equals(initialValue)) { - if (isEdit && initialValue != null) { - // Remove the old value before we add the new one, which is we just - // asserted will be different. - for (SdkSource source : mSources.getSources(SdkSourceCategory.USER_ADDONS)) { - if (initialValue.equals(source.getUrl())) { - mSources.remove(source); - break; - } - } - - } - - // create the source, store it and update the list - SdkSource newSource; - // use url suffix to decide whether this is a SysImg or Addon; - // see SdkSources.loadUserAddons() for another check like this - if (url.endsWith(SdkSysImgConstants.URL_DEFAULT_FILENAME)) { - newSource = new SdkSysImgSource(url, null/*uiName*/); - } else { - newSource = new SdkAddonSource(url, null/*uiName*/); - } - mSources.add(SdkSourceCategory.USER_ADDONS, newSource); - setReturnValue(true); - // notify sources change listeners. This will invoke our own loadUserUrlsList(). - mSources.notifyChangeListeners(); - - // select the new source - IStructuredSelection newSel = new StructuredSelection(newSource); - mUserTableViewer.setSelection(newSel, true /*reveal*/); - } - } - } - - private void on_UserButtonDelete_widgetSelected(SelectionEvent e) { - IStructuredSelection sel = (IStructuredSelection) mUserTableViewer.getSelection(); - String selectedUrl = sel.isEmpty() ? null : sel.getFirstElement().toString(); - - if (selectedUrl == null) { - return; - } - - MessageBox mb = new MessageBox(getShell(), - SWT.YES | SWT.NO | SWT.ICON_QUESTION | SWT.APPLICATION_MODAL); - mb.setText("Delete add-on site"); - mb.setMessage(String.format("Do you want to delete the URL %1$s?", selectedUrl)); - if (mb.open() == SWT.YES) { - for (SdkSource source : mSources.getSources(SdkSourceCategory.USER_ADDONS)) { - if (selectedUrl.equals(source.getUrl())) { - mSources.remove(source); - setReturnValue(true); - mSources.notifyChangeListeners(); - break; - } - } - } - } - - private void on_UserTable_mouseUp(MouseEvent event) { - Point p = new Point(event.x, event.y); - if (mUserTable.getItem(p) == null) { - mUserTable.deselectAll(); - on_UserTableViewer_selectionChanged(null /*event*/); - } - } - - private void on_UserTableViewer_selectionChanged(SelectionChangedEvent event) { - ISelection sel = mUserTableViewer.getSelection(); - mUserButtonDelete.setEnabled(!sel.isEmpty()); - mUserButtonEdit.setEnabled(!sel.isEmpty()); - } - - private void on_SitesTableViewer_checkStateChanged(CheckStateChangedEvent event) { - Object element = event.getElement(); - if (element instanceof SdkSource) { - SdkSource source = (SdkSource) element; - boolean isChecked = event.getChecked(); - if (source.isEnabled() != isChecked) { - setReturnValue(true); - source.setEnabled(isChecked); - mSources.notifyChangeListeners(); - } - } - } - - private void on_SitesTableViewer_selectAll() { - for (Object item : (Object[]) mSitesTableViewer.getInput()) { - if (!mSitesTableViewer.getChecked(item)) { - mSitesTableViewer.setChecked(item, true); - on_SitesTableViewer_checkStateChanged( - new CheckStateChangedEvent(mSitesTableViewer, item, true)); - } - } - } - - private void on_SitesTableViewer_deselectAll() { - for (Object item : (Object[]) mSitesTableViewer.getInput()) { - if (mSitesTableViewer.getChecked(item)) { - mSitesTableViewer.setChecked(item, false); - on_SitesTableViewer_checkStateChanged( - new CheckStateChangedEvent(mSitesTableViewer, item, false)); - } - } - } - - - @Override - protected void postCreate() { - // A runnable to initially load and then update the user urls & sites lists. - final Runnable updateInUiThread = new Runnable() { - @Override - public void run() { - loadUserUrlsList(); - loadSiteUrlsList(); - } - }; - - // A listener that runs when the sources have changed. - // This is most likely called on a worker thread. - mSourcesChangeListener = new Runnable() { - @Override - public void run() { - Shell shell = getShell(); - if (shell != null) { - Display display = shell.getDisplay(); - if (display != null) { - display.syncExec(updateInUiThread); - } - } - } - }; - - mSources.addChangeListener(mSourcesChangeListener); - - // initialize the list - updateInUiThread.run(); - } - - private void loadUserUrlsList() { - SdkSource[] knownSources = mSources.getSources(SdkSourceCategory.USER_ADDONS); - Arrays.sort(knownSources); - - ISelection oldSelection = mUserTableViewer.getSelection(); - - mUserTableViewer.setInput(knownSources); - mUserTableViewer.refresh(); - // initialize buttons' state that depend on the list - on_UserTableViewer_selectionChanged(null /*event*/); - - if (oldSelection != null && !oldSelection.isEmpty()) { - mUserTableViewer.setSelection(oldSelection, true /*reveal*/); - } - } - - private void loadSiteUrlsList() { - SdkSource[] knownSources = mSources.getSources(SdkSourceCategory.ADDONS_3RD_PARTY); - Arrays.sort(knownSources); - - ISelection oldSelection = mSitesTableViewer.getSelection(); - - mSitesTableViewer.setInput(knownSources); - mSitesTableViewer.refresh(); - - if (oldSelection != null && !oldSelection.isEmpty()) { - mSitesTableViewer.setSelection(oldSelection, true /*reveal*/); - } - - // Check the sources which are currently enabled. - ArrayList disabled = new ArrayList(knownSources.length); - for (SdkSource source : knownSources) { - if (source.isEnabled()) { - disabled.add(source); - } - } - mSitesTableViewer.setCheckedElements(disabled.toArray()); - } - - - private static class SourcesContentProvider implements IStructuredContentProvider { - @Override - public void dispose() { - // pass - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // pass - } - - @Override - public Object[] getElements(Object inputElement) { - if (inputElement instanceof SdkSource[]) { - return (Object[]) inputElement; - } else { - return new Object[0]; - } - } - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java index ed0b933a..691284d6 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java @@ -21,11 +21,11 @@ import com.android.sdklib.devices.DeviceManager.DevicesChangedListener; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.repository.ISdkChangeListener; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; +import com.android.sdkuilib.repository.ISdkChangeListener; +import com.android.sdkuilib.ui.AvdDisplayMode; import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -48,23 +48,22 @@ public class AvdManagerPage extends Composite private AvdSelector mAvdSelector; - private final SwtUpdaterData mSwtUpdaterData; + private final SdkContext mSdkContext; private final DeviceManager mDeviceManager; /** * Create the composite. * @param parent The parent of the composite. - * @param swtUpdaterData An instance of {@link SwtUpdaterData}. + * @param sdkContext SDK handler and repo manager */ public AvdManagerPage(Composite parent, int swtStyle, - SwtUpdaterData swtUpdaterData, - DeviceManager deviceManager) { + SdkContext sdkContext) { super(parent, swtStyle); - mSwtUpdaterData = swtUpdaterData; - mSwtUpdaterData.addListeners(this); + mSdkContext = sdkContext; + mSdkContext.getSdkHelper().addListeners(this); - mDeviceManager = deviceManager; + mDeviceManager = mSdkContext.getDeviceManager(); mDeviceManager.registerListener(this); createContents(this); @@ -78,23 +77,16 @@ private void createContents(Composite parent) { label.setLayoutData(new GridData()); try { - if (mSwtUpdaterData != null && mSwtUpdaterData.getAvdManager() != null) { - label.setText(String.format( + label.setText(String.format( "List of existing Android Virtual Devices located at %s", - mSwtUpdaterData.getAvdManager().getBaseAvdFolder())); - } else { - label.setText("Error: cannot find the AVD folder location.\r\n Please set the 'ANDROID_SDK_HOME' env variable."); - } + mSdkContext.getAvdManager().getBaseAvdFolder())); } catch (AndroidLocationException e) { label.setText(e.getMessage()); } mAvdSelector = new AvdSelector(parent, - mSwtUpdaterData.getOsSdkRoot(), - mSwtUpdaterData.getAvdManager(), - DisplayMode.MANAGER, - mSwtUpdaterData.getSdkLog()); - mAvdSelector.setSettingsController(mSwtUpdaterData.getSettingsController()); + mSdkContext, + AvdDisplayMode.MANAGER); } @Override @@ -104,7 +96,7 @@ public void widgetDisposed(DisposeEvent e) { @Override public void dispose() { - mSwtUpdaterData.removeListener(this); + mSdkContext.getSdkHelper().removeListener(this); mDeviceManager.unregisterListener(this); super.dispose(); } @@ -114,16 +106,16 @@ protected void checkSubclass() { // Disable the check that prevents subclassing of SWT components } - public void selectAvd(AvdInfo avdInfo, boolean reloadAvdList) { + public void selectAvd(AvdInfo avd, boolean reloadAvdList) { if (reloadAvdList) { mAvdSelector.refresh(true /*reload*/); // Reloading the AVDs created new objects, so the reference to avdInfo // will never be selected. Instead reselect it based on its unique name. - AvdManager am = mSwtUpdaterData.getAvdManager(); - avdInfo = am.getAvd(avdInfo.getName(), false /*validAvdOnly*/); + AvdManager avdManager = mSdkContext.getAvdManager(); + avd = avdManager.getAvd(avd.getName(), false /*validAvdOnly*/); } - mAvdSelector.setSelection(avdInfo); + mAvdSelector.setSelection(avd); } // -- Start of internal part ---------- @@ -166,7 +158,6 @@ public void onDevicesChanged() { mAvdSelector.refresh(false /*reload*/); } - // End of hiding from SWT Designer //$hide<<$ } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java index 1f14d7f7..74b15402 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java @@ -18,23 +18,23 @@ import com.android.SdkConstants; -import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.updater.SettingsController; -import com.android.sdklib.repository.ISdkChangeListener; + +import com.android.sdkuilib.repository.ISdkChangeListener; import com.android.sdkuilib.internal.repository.AboutDialog; import com.android.sdkuilib.internal.repository.MenuBarWrapper; import com.android.sdkuilib.internal.repository.SettingsDialog; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; import com.android.sdkuilib.internal.repository.ui.DeviceManagerPage.IAvdCreatedListener; -import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; import com.android.sdkuilib.repository.SdkUpdaterWindow; + +import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridLayoutBuilder; import com.android.utils.ILogger; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -50,8 +50,6 @@ import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; -import java.io.File; - /** * This is an intermediate version of the {@link AvdManagerPage} * wrapped in its own standalone window for use from the SDK Manager 2. @@ -64,18 +62,16 @@ public class AvdManagerWindowImpl1 { private final Shell mParentShell; private final AvdInvocationContext mContext; + private final SdkContext mSdkContext; /** Internal data shared between the window and its pages. */ - private final SwtUpdaterData mSwtUpdaterData; /** True if this window created the UpdaterData, in which case it needs to dispose it. */ private final boolean mOwnUpdaterData; - private final DeviceManager mDeviceManager; // --- UI members --- protected Shell mShell; private AvdManagerPage mAvdPage; - private SettingsController mSettingsController; private TabFolder mTabFolder; /** @@ -83,20 +79,19 @@ public class AvdManagerWindowImpl1 { * * @param parentShell Parent shell. * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. + * @param sdkContext SDK handler and repo manager * @param context The {@link AvdInvocationContext} to change the behavior depending on who's * opening the SDK Manager. */ public AvdManagerWindowImpl1( Shell parentShell, ILogger sdkLog, - String osSdkRoot, + SdkContext sdkContext, AvdInvocationContext context) { mParentShell = parentShell; + mSdkContext = sdkContext; mContext = context; - mSwtUpdaterData = new SwtUpdaterData(osSdkRoot, sdkLog); mOwnUpdaterData = true; - mDeviceManager = DeviceManager.createInstance(new File(osSdkRoot), sdkLog); } /** @@ -106,20 +101,18 @@ public AvdManagerWindowImpl1( * to share the same {@link SwtUpdaterData} structure. * * @param parentShell Parent shell. - * @param swtUpdaterData The parent's updater data. + * @param sdkContext SDK handler and repo manager * @param context The {@link AvdInvocationContext} to change the behavior depending on who's * opening the SDK Manager. */ public AvdManagerWindowImpl1( Shell parentShell, - SwtUpdaterData swtUpdaterData, + SdkContext sdkContext, AvdInvocationContext context) { mParentShell = parentShell; mContext = context; - mSwtUpdaterData = swtUpdaterData; + mSdkContext = sdkContext; mOwnUpdaterData = false; - mDeviceManager = DeviceManager.createInstance(new File(mSwtUpdaterData.getOsSdkRoot()), - mSwtUpdaterData.getSdkLog()); } /** @@ -147,7 +140,6 @@ public void open() { display.sleep(); } } - dispose(); //$hide$ } } @@ -202,7 +194,7 @@ private void createAvdTab(TabFolder tabFolder, TabItem avdTabItem) { avdTabItem.setControl(root); GridLayoutBuilder.create(root).columns(1); - mAvdPage = new AvdManagerPage(root, SWT.NONE, mSwtUpdaterData, mDeviceManager); + mAvdPage = new AvdManagerPage(root, SWT.NONE, mSdkContext); GridDataBuilder.create(mAvdPage).fill().grab(); } @@ -212,7 +204,7 @@ private void createDeviceTab(TabFolder tabFolder, TabItem devTabItem) { GridLayoutBuilder.create(root).columns(1); DeviceManagerPage devicePage = - new DeviceManagerPage(root, SWT.NONE, mSwtUpdaterData, mDeviceManager); + new DeviceManagerPage(root, SWT.NONE, mSdkContext, new SdkTargets(mSdkContext)); GridDataBuilder.create(devicePage).fill().grab(); devicePage.setAvdCreatedListener(new IAvdCreatedListener() { @@ -226,7 +218,6 @@ public void onAvdCreated(AvdInfo avdInfo) { }); } - @SuppressWarnings("unused") // MenuBarWrapper works using side effects private void createMenuBar() { Menu menuBar = new Menu(mShell, SWT.BAR); @@ -258,25 +249,25 @@ public void widgetSelected(SelectionEvent event) { new MenuBarWrapper(APP_NAME_MAC_MENU, menuTools) { @Override public void onPreferencesMenuSelected() { - SettingsDialog sd = new SettingsDialog(mShell, mSwtUpdaterData); + SettingsDialog sd = new SettingsDialog(mShell, mSdkContext); sd.open(); } @Override public void onAboutMenuSelected() { - AboutDialog ad = new AboutDialog(mShell, mSwtUpdaterData); + AboutDialog ad = new AboutDialog(mShell, mSdkContext); ad.open(); } @Override public void printError(String format, Object... args) { - if (mSwtUpdaterData != null) { - mSwtUpdaterData.getSdkLog().error(null, format, args); + if (mSdkContext != null) { + mSdkContext.getSdkLog().error(null, format, args); } } }; } catch (Throwable e) { - mSwtUpdaterData.getSdkLog().error(e, "Failed to setup menu bar"); + mSdkContext.getSdkLog().error(e, "Failed to setup menu bar"); e.printStackTrace(); } } @@ -293,7 +284,7 @@ public void printError(String format, Object... args) { * Adds a new listener to be notified when a change is made to the content of the SDK. */ public void addListener(ISdkChangeListener listener) { - mSwtUpdaterData.addListeners(listener); + mSdkContext.getSdkHelper().addListeners(listener); } /** @@ -301,7 +292,7 @@ public void addListener(ISdkChangeListener listener) { * the SDK. */ public void removeListener(ISdkChangeListener listener) { - mSwtUpdaterData.removeListener(listener); + mSdkContext.getSdkHelper().removeListener(listener); } // --- Internals & UI Callbacks ----------- @@ -310,9 +301,7 @@ public void removeListener(ISdkChangeListener listener) { * Called before the UI is created. */ private void preCreateContent() { - mSwtUpdaterData.setWindowShell(mShell); - // We need the UI factory to create the UI - mSwtUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay())); + mSdkContext.getSdkHelper().setWindowShell(mShell); // Note: we can't create the TaskFactory yet because we need the UI // to be created first, so this is done in postCreateContent(). } @@ -326,15 +315,11 @@ private void preCreateContent() { private boolean postCreateContent() { setWindowImage(mShell); - setupSources(); - initializeSettings(); - - if (mSwtUpdaterData.checkIfInitFailed()) { + if (!initializeSettings()) { return false; } - - mSwtUpdaterData.broadcastOnSdkLoaded(); - + // TODO - Consider how to signal SDK loaded + //mSdkContext.getSdkHelper().broadcastOnSdkLoaded(mSdkContext.getSdkLog()); return true; } @@ -349,8 +334,8 @@ private void setWindowImage(Shell shell) { imageName = "android_icon_128.png"; } - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { shell.setImage(imgFactory.getImageByName(imageName)); } @@ -361,54 +346,41 @@ private void setWindowImage(Shell shell) { * Called by the main loop when the window has been disposed. */ private void dispose() { - mSwtUpdaterData.getSources().saveUserAddons(mSwtUpdaterData.getSdkLog()); + //mSdkContext.getSources().saveUserAddons(mSdkContext.getSdkLog()); } /** * Callback called when the window shell is disposed. */ private void onAndroidSdkUpdaterDispose() { - if (mOwnUpdaterData && mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mOwnUpdaterData && mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { imgFactory.dispose(); } } } - /** - * Used to initialize the sources. - */ - private void setupSources() { - mSwtUpdaterData.setupDefaultSources(); - } - /** * Initializes settings. * This must be called after addExtraPages(), which created a settings page. * Iterate through all the pages to find the first (and supposedly unique) setting page, * and use it to load and apply these settings. */ - private void initializeSettings() { - mSettingsController = mSwtUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); + private boolean initializeSettings() { + return mSdkContext.getSettings().initialize(mSdkContext.getSdkLog()); } private void onSdkManager() { - ITaskFactory oldFactory = mSwtUpdaterData.getTaskFactory(); - try { SdkUpdaterWindowImpl2 win = new SdkUpdaterWindowImpl2( mShell, - mSwtUpdaterData, + mSdkContext, SdkUpdaterWindow.SdkInvocationContext.AVD_MANAGER); win.open(); } catch (Exception e) { - mSwtUpdaterData.getSdkLog().error(e, "SDK Manager window error"); - } finally { - mSwtUpdaterData.setTaskFactory(oldFactory); + mSdkContext.getSdkLog().error(e, "SDK Manager window error"); } } } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java index bd20ef82..83300337 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java @@ -18,7 +18,6 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.sdklib.SystemImage; import com.android.sdklib.devices.Device; import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.devices.DeviceManager.DeviceFilter; @@ -28,16 +27,18 @@ import com.android.sdklib.devices.Storage; import com.android.sdklib.devices.Storage.Unit; import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.repository.ISdkChangeListener; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.icons.ImageFactory.Filter; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.base.resources.ImageFactory.ImageEditor; import com.android.sdkuilib.internal.widgets.AvdCreationDialog; import com.android.sdkuilib.internal.widgets.AvdSelector; import com.android.sdkuilib.internal.widgets.DeviceCreationDialog; +import com.android.sdkuilib.repository.ISdkChangeListener; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridLayoutBuilder; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; @@ -102,7 +103,8 @@ public interface IAvdCreatedListener { public void onAvdCreated(AvdInfo createdAvdInfo); } - private final SwtUpdaterData mSwtUpdaterData; + private final SdkContext mSdkContext; + private final SdkTargets mSdkTargets; private final DeviceManager mDeviceManager; private Table mTable; private Button mNewButton; @@ -116,9 +118,9 @@ public interface IAvdCreatedListener { private int mImageWidth; private boolean mDisableRefresh; private IAvdCreatedListener mAvdCreatedListener; - private final Filter mUserColorFilter = new Filter() { + private final ImageEditor mUserColorFilter = new ImageEditor() { @Override - public Image filter(Image source) { + public ImageData edit(Image source) { ImageData srcData = source.getImageData(); // swap green and blue @@ -131,25 +133,26 @@ public Image filter(Image source) { p.blueShift = p.greenShift; p.greenShift = b; - return new Image(source.getDevice(), srcData); + return srcData; } }; /** * Create the composite. * @param parent The parent of the composite. - * @param swtUpdaterData An instance of {@link SwtUpdaterData}. + * @param SdkContext An instance of {@link SdkContext}. */ public DeviceManagerPage(Composite parent, int swtStyle, - SwtUpdaterData swtUpdaterData, - DeviceManager deviceManager) { + SdkContext sdkContext, + SdkTargets sdkTargets) { super(parent, swtStyle); - mSwtUpdaterData = swtUpdaterData; - mSwtUpdaterData.addListeners(this); + mSdkContext = sdkContext; + mSdkTargets = sdkTargets; + mSdkContext.getSdkHelper().addListeners(this); - mDeviceManager = deviceManager; + mDeviceManager = mSdkContext.getDeviceManager(); mDeviceManager.registerListener(this); createContents(this); @@ -163,7 +166,7 @@ public void setAvdCreatedListener(IAvdCreatedListener avdCreatedListener) { private void createContents(Composite parent) { // get some bitmaps. - mImageFactory = new ImageFactory(parent.getDisplay()); + mImageFactory = mSdkContext.getSdkHelper().getImageFactory(); mUserImage = getTagImage(null /*tag*/, true /*isUser*/); mDeviceImage = getTagImage(null /*tag*/, false /*isUser*/); mImageWidth = Math.max(mDeviceImage.getImageData().width, @@ -316,7 +319,7 @@ public void widgetDisposed(DisposeEvent e) { @Override public void dispose() { - mSwtUpdaterData.removeListener(this); + mSdkContext.getSdkHelper().removeListener(this); mDeviceManager.unregisterListener(this); super.dispose(); } @@ -484,14 +487,14 @@ private List fillDevices( // Generate a list of the AVD names using these devices Map> device2avdMap = new HashMap>(); - for (AvdInfo avd : mSwtUpdaterData.getAvdManager().getAllAvds()) { + for (AvdInfo avd : mSdkContext.getAvdManager().getAllAvds()) { String n = avd.getDeviceName(); String m = avd.getDeviceManufacturer(); if (n == null || m == null || n.isEmpty() || m.isEmpty()) { continue; } for (Device device : devices) { - if (m.equals(device.getManufacturer()) && n.equals(device.getName())) { + if (m.equals(device.getManufacturer()) && n.equals(device.getDisplayName())) { List list = device2avdMap.get(device); if (list == null) { list = new LinkedList(); @@ -598,7 +601,7 @@ private static String getPrettyName(Device d, boolean leadZeroes) { if (d == null) { return ""; } - String name = d.getName(); + String name = d.getDisplayName(); if (name.equals("3.7 FWVGA slider")) { //$NON-NLS-1$ // Fix metadata: this one entry doesn't have "in" like the rest of them name = "3.7in FWVGA slider"; //$NON-NLS-1$ @@ -654,7 +657,7 @@ private void onNewDevice() { DeviceCreationDialog dlg = new DeviceCreationDialog( getShell(), mDeviceManager, - mSwtUpdaterData.getImageFactory(), + mSdkContext.getSdkHelper().getImageFactory(), null /*device*/); if (dlg.open() == Window.OK) { onRefresh(); @@ -674,7 +677,7 @@ private void onEditDevice() { DeviceCreationDialog dlg = new DeviceCreationDialog( getShell(), mDeviceManager, - mSwtUpdaterData.getImageFactory(), + mSdkContext.getSdkHelper().getImageFactory(), ci.mDevice); if (dlg.open() == Window.OK) { onRefresh(); @@ -720,9 +723,8 @@ private void onCreateAvd() { } final AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(), - mSwtUpdaterData.getAvdManager(), - mImageFactory, - mSwtUpdaterData.getSdkLog(), + mSdkContext, + mSdkTargets, null); dlg.selectInitialDevice(ci.mDevice); @@ -760,13 +762,13 @@ private boolean selectCellByName(CellInfo selected) { if (mTable.isDisposed() || selected == null || selected.mDevice == null) { return false; } - String name = selected.mDevice.getName(); + String name = selected.mDevice.getDisplayName(); for (int n = mTable.getItemCount() - 1; n >= 0; n--) { TableItem item = mTable.getItem(n); Object data = item.getData(); if (data instanceof CellInfo) { CellInfo ci = (CellInfo) data; - if (ci != null && ci.mDevice != null && name.equals(ci.mDevice.getName())) { + if (ci != null && ci.mDevice != null && name.equals(ci.mDevice.getDisplayName())) { // Same cell object. Select it. mTable.select(n); return true; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/LogWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/LogWindow.java index 5977f315..2e79601c 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/LogWindow.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/LogWindow.java @@ -48,7 +48,7 @@ * the floating window is hidden but not closed. This way it can easily accumulate * all the log. */ -class LogWindow implements ILogUiProvider { +public class LogWindow implements ILogUiProvider { private Shell mParentShell; private Shell mShell; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPage.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPage.java index bb72ea18..933f8a6c 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPage.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPage.java @@ -16,27 +16,19 @@ package com.android.sdkuilib.internal.repository.ui; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.updater.PkgItem; -import com.android.sdklib.internal.repository.updater.PkgItem.PkgState; -import com.android.sdklib.repository.ISdkChangeListener; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgCategoryApi; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; @@ -68,27 +60,52 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import com.android.annotations.NonNull; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.PackageOperation; +import com.android.repository.api.ProgressIndicator; +import com.android.repository.api.ProgressRunner; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoManager.RepoLoadedCallback; +import com.android.repository.api.Uninstaller; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.Archive; +import com.android.repository.impl.meta.RepositoryPackages; +import com.android.repository.util.InstallerUtil; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.repository.installer.SdkInstallerUtil; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskFactory; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.LoadPackagesRequest; +import com.android.sdkuilib.internal.repository.PackageManager; +import com.android.sdkuilib.internal.repository.content.CategoryKeyType; +import com.android.sdkuilib.internal.repository.content.PackageAnalyser; +import com.android.sdkuilib.internal.repository.content.PackageAnalyser.PkgState; +import com.android.sdkuilib.internal.repository.content.PackageContentProvider; +import com.android.sdkuilib.internal.repository.content.PkgCategory; +import com.android.sdkuilib.internal.repository.content.PkgCellAgent; +import com.android.sdkuilib.internal.repository.content.PkgCellLabelProvider; +import com.android.sdkuilib.internal.repository.content.PkgItem; +import com.android.sdkuilib.internal.repository.content.PkgTreeColumnViewerLabelProvider; +import org.eclipse.andmore.base.resources.ImageFactory; +import com.android.sdkuilib.internal.tasks.ILogUiProvider; +import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; +import com.android.sdkuilib.ui.GridDataBuilder; +import com.android.sdkuilib.ui.GridLayoutBuilder; /** * Page that displays both locally installed packages as well as all known * remote available packages. This gives an overview of what is installed * vs what is available and allows the user to update or install packages. */ -public final class PackagesPage extends Composite implements ISdkChangeListener { +public final class PackagesPage extends Composite { enum MenuAction { - RELOAD (SWT.NONE, "Reload"), - SHOW_ADDON_SITES (SWT.NONE, "Manage Add-on Sites..."), - TOGGLE_SHOW_ARCHIVES (SWT.CHECK, "Show Archives Details"), - TOGGLE_SHOW_INSTALLED_PKG (SWT.CHECK, "Show Installed Packages"), + RELOAD (SWT.NONE, "Reload"), + //TOGGLE_SHOW_INSTALLED_PKG (SWT.CHECK, "Show Installed Packages"), TOGGLE_SHOW_OBSOLETE_PKG (SWT.CHECK, "Show Obsolete Packages"), - TOGGLE_SHOW_UPDATE_NEW_PKG (SWT.CHECK, "Show Updates/New Packages") + TOGGLE_SHOW_NEW_PKG (SWT.CHECK, "Show New Packages") ; private final int mMenuStyle; @@ -108,18 +125,26 @@ public String getMenuTitle() { } }; - private final Map mMenuActions = new HashMap(); + // Column ids + public static final int NAME = 1; + public static final int API = 2; + public static final int REVISION = 3; + public static final int STATUS = 4; - private final PackagesPageImpl mImpl; - private final SdkInvocationContext mContext; + private final Map mMenuActions = new HashMap(); + + private final SdkContext mSdkContext; + //private final SdkInvocationContext mContext; + private final PackageAnalyser mPackageAnalyser; private boolean mDisplayArchives = false; private boolean mOperationPending; + private ProgressRunner mProgressRunner; private Composite mGroupPackages; private Text mTextSdkOsPath; private Button mCheckFilterObsolete; - private Button mCheckFilterInstalled; + //private Button mCheckFilterInstalled; private Button mCheckFilterNew; private Composite mGroupOptions; private Composite mGroupSdk; @@ -128,58 +153,26 @@ public String getMenuTitle() { private Font mTreeFontItalic; private TreeColumn mTreeColumnName; private CheckboxTreeViewer mTreeViewer; + private ILogUiProvider mSdkProgressControl; + private ITaskFactory mTaskFactory; public PackagesPage( Composite parent, int swtStyle, - SwtUpdaterData swtUpdaterData, - SdkInvocationContext context) { + SdkContext sdkContext, + SdkInvocationContext context) + { super(parent, swtStyle); - mImpl = new PackagesPageImpl(swtUpdaterData) { - @Override - protected boolean isUiDisposed() { - return mGroupPackages == null || mGroupPackages.isDisposed(); - }; - @Override - protected void syncExec(Runnable runnable) { - if (!isUiDisposed()) { - mGroupPackages.getDisplay().syncExec(runnable); - } - }; - - @Override - protected void syncViewerSelection() { - PackagesPage.this.syncViewerSelection(); - } - - @Override - protected void refreshViewerInput() { - PackagesPage.this.refreshViewerInput(); - } - - @Override - protected Font getTreeFontItalic() { - return mTreeFontItalic; - } - - @Override - protected void loadPackages(boolean useLocalCache, boolean overrideExisting) { - PackagesPage.this.loadPackages(useLocalCache, overrideExisting); - } - }; - mContext = context; - + mSdkContext = sdkContext; + mPackageAnalyser = new PackageAnalyser(sdkContext); + //mContext = context; createContents(this); postCreate(); //$hide$ } - public void performFirstLoad() { - mImpl.performFirstLoad(); - } - - @SuppressWarnings("unused") - private void createContents(Composite parent) { - GridLayoutBuilder.create(parent).noMargins().columns(2); + private void createContents(Composite parent) + { + GridLayoutBuilder.create(parent).noMargins().columns(2); mGroupSdk = new Composite(parent, SWT.NONE); GridDataBuilder.create(mGroupSdk).hFill().vCenter().hGrab().hSpan(2); @@ -199,47 +192,24 @@ private void createContents(Composite parent) { GridLayoutBuilder.create(groupPackages).columns(1); mTreeViewer = new CheckboxTreeViewer(groupPackages, SWT.BORDER); - mImpl.setITreeViewer(new PackagesPageImpl.ICheckboxTreeViewer() { - @Override - public Object getInput() { - return mTreeViewer.getInput(); - } - - @Override - public void setInput(List cats) { - mTreeViewer.setInput(cats); - } - - @Override - public void setContentProvider(PkgContentProvider pkgContentProvider) { - mTreeViewer.setContentProvider(pkgContentProvider); - } - - @Override - public void refresh() { - mTreeViewer.refresh(); - } - - @Override - public Object[] getCheckedElements() { - return mTreeViewer.getCheckedElements(); - } - }); - mTreeViewer.addFilter(new ViewerFilter() { + mTreeViewer.addFilter(new ViewerFilter() + { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { return filterViewerItem(element); } }); - mTreeViewer.addCheckStateListener(new ICheckStateListener() { + mTreeViewer.addCheckStateListener(new ICheckStateListener() + { @Override public void checkStateChanged(CheckStateChangedEvent event) { onTreeCheckStateChanged(event); //$hide$ } }); - mTreeViewer.addDoubleClickListener(new IDoubleClickListener() { + mTreeViewer.addDoubleClickListener(new IDoubleClickListener() + { @Override public void doubleClick(DoubleClickEvent event) { onTreeDoubleClick(event); //$hide$ @@ -278,35 +248,31 @@ public void doubleClick(DoubleClickEvent event) { treeColumn4.setAlignment(SWT.LEAD); treeColumn4.setWidth(190); - mImpl.setIColumns( - wrapColumn(columnName), - wrapColumn(columnApi), - wrapColumn(columnRevision), - wrapColumn(columnStatus)); - mGroupOptions = new Composite(groupPackages, SWT.NONE); GridDataBuilder.create(mGroupOptions).hFill().vCenter().hGrab(); - GridLayoutBuilder.create(mGroupOptions).columns(7).noMargins(); + GridLayoutBuilder.create(mGroupOptions).columns(4).noMargins(); - // Options line 1, 7 columns + // Options line 1, 4 columns Label label3 = new Label(mGroupOptions, SWT.NONE); label3.setText("Show:"); - + GridDataBuilder.create(label3).vSpan(2).vTop(); mCheckFilterNew = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterNew.setText("Updates/New"); - mCheckFilterNew.setToolTipText("Show Updates and New"); - mCheckFilterNew.addSelectionListener(new SelectionAdapter() { + mCheckFilterNew.setText("New"); + mCheckFilterNew.setToolTipText("Show New"); + mCheckFilterNew.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { refreshViewerInput(); } }); mCheckFilterNew.setSelection(true); - +/* mCheckFilterInstalled = new Button(mGroupOptions, SWT.CHECK); mCheckFilterInstalled.setToolTipText("Show Installed"); - mCheckFilterInstalled.addSelectionListener(new SelectionAdapter() { + mCheckFilterInstalled.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { refreshViewerInput(); @@ -314,50 +280,48 @@ public void widgetSelected(SelectionEvent e) { }); mCheckFilterInstalled.setSelection(true); mCheckFilterInstalled.setText("Installed"); - - new Label(mGroupOptions, SWT.NONE); - - Link linkSelectNew = new Link(mGroupOptions, SWT.NONE); - // Note for i18n: we need to identify which link is used, and this is done by using the - // text itself so for translation purposes we want to keep the link strings separate. - final String strLinkNew = "New"; - final String strLinkUpdates = "Updates"; - linkSelectNew.setText( - String.format("Select %1$s or %2$s", strLinkNew, strLinkUpdates)); - linkSelectNew.setToolTipText("Selects all items that are either new or updates."); - GridDataBuilder.create(linkSelectNew).hFill(); - linkSelectNew.addSelectionListener(new SelectionAdapter() { +*/ + //new Label(mGroupOptions, SWT.NONE); + + Link linkSelectUpdates = new Link(mGroupOptions, SWT.NONE); + linkSelectUpdates.setText("Select Updates"); + linkSelectUpdates.setToolTipText("Selects all items that are updates."); + //GridDataBuilder.create(linkSelectUpdates).hFill(); + linkSelectUpdates.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); - boolean selectNew = e.text == null || e.text.equals(strLinkNew); - onSelectNewUpdates(selectNew, !selectNew, false/*selectTop*/); + onSelectPackages(true, false); // selectTop } }); // placeholder between "select all" and "install" - Label placeholder = new Label(mGroupOptions, SWT.NONE); - GridDataBuilder.create(placeholder).hFill().hGrab(); + //Label placeholder = new Label(mGroupOptions, SWT.NONE); + //GridDataBuilder.create(placeholder).hFill().hGrab(); mButtonInstall = new Button(mGroupOptions, SWT.NONE); mButtonInstall.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() mButtonInstall.setToolTipText("Install one or more packages"); - GridDataBuilder.create(mButtonInstall).vCenter().wHint(150); - mButtonInstall.addSelectionListener(new SelectionAdapter() { + GridDataBuilder.create(mButtonInstall).vCenter().wHint(150).hFill().hGrab().hRight(); + mButtonInstall.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { onButtonInstall(); //$hide$ } }); - // Options line 2, 7 columns + // Options line 2, 4 columns - new Label(mGroupOptions, SWT.NONE); + //Label placeholder2 = new Label(mGroupOptions, SWT.NONE); + //GridDataBuilder.create(placeholder2).hFill().hGrab(); mCheckFilterObsolete = new Button(mGroupOptions, SWT.CHECK); mCheckFilterObsolete.setText("Obsolete"); mCheckFilterObsolete.setToolTipText("Also show obsolete packages"); - mCheckFilterObsolete.addSelectionListener(new SelectionAdapter() { + mCheckFilterObsolete.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { refreshViewerInput(); @@ -366,14 +330,15 @@ public void widgetSelected(SelectionEvent e) { mCheckFilterObsolete.setSelection(false); // placeholder before "deselect" - new Label(mGroupOptions, SWT.NONE); - new Label(mGroupOptions, SWT.NONE); + //new Label(mGroupOptions, SWT.NONE); + //new Label(mGroupOptions, SWT.NONE); Link linkDeselect = new Link(mGroupOptions, SWT.NONE); linkDeselect.setText("Deselect All"); linkDeselect.setToolTipText("Deselects all the currently selected items"); - GridDataBuilder.create(linkDeselect).hFill(); - linkDeselect.addSelectionListener(new SelectionAdapter() { + //GridDataBuilder.create(linkDeselect).hFill(); + linkDeselect.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); @@ -382,37 +347,47 @@ public void widgetSelected(SelectionEvent e) { }); // placeholder between "deselect" and "delete" - placeholder = new Label(mGroupOptions, SWT.NONE); - GridDataBuilder.create(placeholder).hFill().hGrab(); + //placeholder = new Label(mGroupOptions, SWT.NONE); + //GridDataBuilder.create(placeholder).hFill().hGrab(); mButtonDelete = new Button(mGroupOptions, SWT.NONE); mButtonDelete.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() mButtonDelete.setToolTipText("Delete one ore more installed packages"); - GridDataBuilder.create(mButtonDelete).vCenter().wHint(150); - mButtonDelete.addSelectionListener(new SelectionAdapter() { + GridDataBuilder.create(mButtonDelete).vCenter().wHint(150).hFill().hGrab().hRight(); + mButtonDelete.addSelectionListener(new SelectionAdapter() + { @Override public void widgetSelected(SelectionEvent e) { onButtonDelete(); //$hide$ } }); - } - - private PackagesPageImpl.ITreeViewerColumn wrapColumn(final TreeViewerColumn column) { - return new PackagesPageImpl.ITreeViewerColumn() { + FontData fontData = tree.getFont().getFontData()[0]; + fontData.setStyle(SWT.ITALIC); + mTreeFontItalic = new Font(tree.getDisplay(), fontData); + tree.addDisposeListener(new DisposeListener() { @Override - public void setLabelProvider(ColumnLabelProvider labelProvider) { - column.setLabelProvider(labelProvider); + public void widgetDisposed(DisposeEvent e) { + mTreeFontItalic.dispose(); + mTreeFontItalic = null; } - }; + }); + mTreeViewer.setContentProvider(new PackageContentProvider(mSdkContext, mTreeViewer)); + PkgCellAgent pkgCellAgent = new PkgCellAgent(mSdkContext, mPackageAnalyser, mTreeFontItalic); + columnApi.setLabelProvider( + new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(pkgCellAgent, PkgCellLabelProvider.API))); + columnName.setLabelProvider( + new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(pkgCellAgent, PkgCellLabelProvider.NAME))); + columnStatus.setLabelProvider( + new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(pkgCellAgent, PkgCellLabelProvider.STATUS))); + columnRevision.setLabelProvider( + new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(pkgCellAgent, PkgCellLabelProvider.REVISION))); } private Image getImage(String filename) { - if (mImpl.mSwtUpdaterData != null) { - ImageFactory imgFactory = mImpl.mSwtUpdaterData.getImageFactory(); + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { return imgFactory.getImageByName(filename); } - } return null; } @@ -425,37 +400,22 @@ private Image getImage(String filename) { // --- menu interactions --- public void registerMenuAction(final MenuAction action, MenuItem item) { - item.addSelectionListener(new SelectionAdapter() { + item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - Button button = null; + Button button = null; switch (action) { case RELOAD: - mImpl.fullReload(); - break; - case SHOW_ADDON_SITES: - AddonSitesDialog d = new AddonSitesDialog(getShell(), mImpl.mSwtUpdaterData); - if (d.open()) { - mImpl.loadPackages(); - } - break; - case TOGGLE_SHOW_ARCHIVES: - mDisplayArchives = !mDisplayArchives; - // Force the viewer to be refreshed - ((PkgContentProvider) mTreeViewer.getContentProvider()). - setDisplayArchives(mDisplayArchives); - mTreeViewer.setInput(null); - refreshViewerInput(); - syncViewerSelection(); - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; + startLoadPackages(); break; +// case TOGGLE_SHOW_INSTALLED_PKG: +// button = mCheckFilterInstalled; +// break; case TOGGLE_SHOW_OBSOLETE_PKG: button = mCheckFilterObsolete; break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: + case TOGGLE_SHOW_NEW_PKG: button = mCheckFilterNew; break; } @@ -487,7 +447,7 @@ public void widgetSelected(SelectionEvent e) { } updateMenuCheckmarks(); - } + } }); mMenuActions.put(action, item); @@ -496,7 +456,6 @@ public void widgetSelected(SelectionEvent e) { // --- internal methods --- private void updateMenuCheckmarks() { - for (Entry entry : mMenuActions.entrySet()) { MenuAction action = entry.getKey(); MenuItem item = entry.getValue(); @@ -509,20 +468,16 @@ private void updateMenuCheckmarks() { Button button = null; switch (action) { - case TOGGLE_SHOW_ARCHIVES: - value = mDisplayArchives; - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; - break; + //case TOGGLE_SHOW_INSTALLED_PKG: + // button = mCheckFilterInstalled; + // break; case TOGGLE_SHOW_OBSOLETE_PKG: button = mCheckFilterObsolete; break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: + case TOGGLE_SHOW_NEW_PKG: button = mCheckFilterNew; break; case RELOAD: - case SHOW_ADDON_SITES: // No checkmark to update break; } @@ -538,60 +493,71 @@ private void updateMenuCheckmarks() { } private void postCreate() { - mImpl.postCreate(); - - if (mImpl.mSwtUpdaterData != null) { - mTextSdkOsPath.setText(mImpl.mSwtUpdaterData.getOsSdkRoot()); - } + mTextSdkOsPath.setText(mSdkContext.getLocation().toString()); - ((PkgContentProvider) mTreeViewer.getContentProvider()).setDisplayArchives( + ((PackageContentProvider) mTreeViewer.getContentProvider()).setDisplayArchives( mDisplayArchives); ColumnViewerToolTipSupport.enableFor(mTreeViewer, ToolTip.NO_RECREATE); - Tree tree = mTreeViewer.getTree(); - FontData fontData = tree.getFont().getFontData()[0]; - fontData.setStyle(SWT.ITALIC); - mTreeFontItalic = new Font(tree.getDisplay(), fontData); - - tree.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - mTreeFontItalic.dispose(); - mTreeFontItalic = null; - } - }); } - private void loadPackages(boolean useLocalCache, boolean overrideExisting) { - if (mImpl.mSwtUpdaterData == null) { - return; - } - - // LoadPackage is synchronous but does not block the UI. - // Consequently it's entirely possible for the user - // to request the app to close whilst the packages are loading. Any - // action done after loadPackages must check the UI hasn't been - // disposed yet. Otherwise hilarity ensues. - + private void startLoadPackages() { + if (mTreeColumnName.isDisposed()) { // If the UI got disposed, don't try to load anything since we won't be // able to display it anyway. return; } - + // Packages will be loaded when onReady() is called + if (mProgressRunner == null) + return; mTreeColumnName.setImage(getImage(PackagesPageIcons.ICON_SORT_BY_API)); - mImpl.loadPackagesImpl(useLocalCache, overrideExisting); + PackageManager packageManager = mSdkContext.getPackageManager(); + LoadPackagesRequest loadPackagesRequest = new LoadPackagesRequest(mProgressRunner); + //RepoLoadedCallback onLocalComplete = new RepoLoadedCallback(){ + + // @Override + // public void doRun(RepositoryPackages packages) { + // }}; + RepoLoadedCallback onSuccess = new RepoLoadedCallback(){ + @Override + public void doRun(RepositoryPackages packages) { + if (!(mGroupPackages == null || mGroupPackages.isDisposed())) + { + packageManager.setPackages(packages); + mPackageAnalyser.loadPackages(); + mGroupPackages.getDisplay().syncExec(new Runnable(){ + + @Override + public void run() { + // automatically select all new and update packages. + Object[] checked = mTreeViewer.getCheckedElements(); + if (checked == null || checked.length == 0) + onSelectPackages( + true, //selectUpdates, + true); //selectTop + refreshViewerInput(); + }}); + mSdkProgressControl.setDescription("Done loading packages."); + } + }}; + Runnable onError = new Runnable(){ + @Override + public void run() { + mSdkProgressControl.setDescription("Package operation did not complete due to error or cancellation"); + }}; + //loadPackagesRequest.setOnLocalComplete(Collections.singletonList(onLocalComplete)); + loadPackagesRequest.setOnSuccess(Collections.singletonList(onSuccess)); + loadPackagesRequest.setOnError(Collections.singletonList(onError)); + packageManager.requestRepositoryPackages(loadPackagesRequest); } private void refreshViewerInput() { - // Dynamically update the table while we load after each source. - // Since the official Android source gets loaded first, it makes the - // window look non-empty a lot sooner. if (!mGroupPackages.isDisposed()) { try { - mImpl.setViewerInput(); + setViewerInput(); } catch (Exception ignore) {} // set the initial expanded state @@ -601,13 +567,30 @@ private void refreshViewerInput() { updateMenuCheckmarks(); } } + + /** + * Invoked from {@link #refreshViewerInput()} to actually either set the + * input of the tree viewer or refresh it if it's the same input + * object. + */ + protected void setViewerInput() { + List> cats = mPackageAnalyser.getApiCategories(); + if (mTreeViewer.getInput() != cats) { + // set initial input + mTreeViewer.setInput(cats); + } else { + // refresh existing, which preserves the expanded state, the selection + // and the checked state. + mTreeViewer.refresh(); + } + } /** * Decide whether to keep an item in the current tree based on user-chosen filter options. */ private boolean filterViewerItem(Object treeElement) { if (treeElement instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) treeElement; + PkgCategory cat = (PkgCategory) treeElement; if (!cat.getItems().isEmpty()) { // A category is hidden if all of its content is hidden. @@ -630,15 +613,15 @@ private boolean filterViewerItem(Object treeElement) { return false; } } - +/* if (!mCheckFilterInstalled.getSelection()) { if (item.getState() == PkgState.INSTALLED) { return false; } } - +*/ if (!mCheckFilterNew.getSelection()) { - if (item.getState() == PkgState.NEW || item.hasUpdatePkg()) { + if (item.getState() == PkgState.NEW ) { //|| item.hasUpdatePkg() return false; } } @@ -662,24 +645,21 @@ private void expandInitial(Object elem) { if (mTreeViewer != null && !mTreeViewer.getTree().isDisposed()) { boolean enablePreviews = - mImpl.mSwtUpdaterData.getSettingsController().getSettings().getEnablePreviews(); + mSdkContext.getSettings().getEnablePreviews(); mTreeViewer.setExpandedState(elem, true); nextCategory: for (Object pkg : ((ITreeContentProvider) mTreeViewer.getContentProvider()). getChildren(elem)) { if (pkg instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) pkg; - + PkgCategory cat = (PkgCategory) pkg; // Always expand the Tools category (and the preview one, if enabled) - if (cat.getKey().equals(PkgCategoryApi.KEY_TOOLS) || + if ((cat.getKeyType() == CategoryKeyType.TOOLS) || (enablePreviews && - cat.getKey().equals(PkgCategoryApi.KEY_TOOLS_PREVIEW))) { + (cat.getKeyType() == CategoryKeyType.TOOLS_PREVIEW))) { expandInitial(pkg); continue nextCategory; } - - for (PkgItem item : cat.getItems()) { if (item.getState() == PkgState.INSTALLED) { expandInitial(pkg); @@ -831,21 +811,23 @@ private void selectCompatibleArchives(Object pkg, ITreeContentProvider provider) } /** - * Checks all PkgItems that are either new or have updates or select top platform - * for initial run. + * Mark packages as checked according to selection criteria. */ - private void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { + private void onSelectPackages(boolean selectUpdates, boolean selectTop) { // This will update the tree's "selected" state and then invoke syncViewerSelection() // which will in turn update tree. - mImpl.onSelectNewUpdates(selectNew, selectUpdates, selectTop); + mPackageAnalyser.checkNewUpdateItems( + selectUpdates, + selectTop); + mTreeViewer.setInput(mPackageAnalyser.getApiCategories()); + syncViewerSelection(); } /** * Deselect all checked PkgItems. */ private void onDeselectAll() { - // This does not update the tree itself, syncViewerSelection does it below. - mImpl.onDeselectAll(); + mPackageAnalyser.uncheckAllItems(); syncViewerSelection(); } @@ -910,7 +892,7 @@ private void endOperationPending() { */ private void updateButtonsState() { if (!mButtonInstall.isDisposed()) { - int numPackages = getArchivesForInstall(null /*archives*/); + int numPackages = getPackagesForInstall(null /*archives*/); mButtonInstall.setEnabled((numPackages > 0) && !mOperationPending); mButtonInstall.setText( @@ -936,115 +918,101 @@ private void updateButtonsState() { * Collects the packages to be installed and shows the installation window. */ private void onButtonInstall() { - ArrayList archives = new ArrayList(); - getArchivesForInstall(archives); + List outPackages = new ArrayList<>(); + getPackagesForInstall(outPackages); + List remotes = new ArrayList<>(); + Map updateMap = new HashMap<>(); + for (PkgItem item: outPackages) { + RemotePackage remotePackage = (RemotePackage)item.getMainPackage(); + remotes.add(remotePackage); + if (item.hasUpdatePkg()) + updateMap.put(remotePackage, item.getUpdatePkg()); + } + ProgressIndicator progress = mSdkContext.getProgressIndicator(); + remotes = InstallerUtil.computeRequiredPackages( + remotes, mSdkContext.getPackages(), progress); + if (remotes == null) { + progress.logWarning("Unable to compute a complete list of dependencies."); + return; + } + Iterator iterator = remotes.iterator(); + while (iterator.hasNext()) + { + if (updateMap.keySet().contains(iterator.next())) + iterator.remove(); + } + boolean needsRefresh = false; + try { + beginOperationPending(); + List acceptedRemotes = null; + SdkUpdaterChooserDialog dialog = + new SdkUpdaterChooserDialog(getShell(), mSdkContext, updateMap.values(), remotes); + dialog.open(); + + acceptedRemotes = dialog.getResult(); + needsRefresh = (acceptedRemotes != null) && (acceptedRemotes.size() > 0); + if (needsRefresh) { + int count = mSdkContext.getPackageManager().installPackages(remotes, acceptedRemotes, mTaskFactory, 0); + if (count == 0) { + needsRefresh = false; + mSdkProgressControl.setDescription("Done. Nothing was installed."); + } + else { + mSdkProgressControl.setDescription(String.format("Done. %1$d %2$s installed.", + count, + count == 1 ? "package" : "packages")); - if (mImpl.mSwtUpdaterData != null) { - boolean needsRefresh = false; - try { - beginOperationPending(); - - List installed = mImpl.mSwtUpdaterData.updateOrInstallAll_WithGUI( - archives, - mCheckFilterObsolete.getSelection() /* includeObsoletes */, - mContext == SdkInvocationContext.IDE ? - SwtUpdaterData.TOOLS_MSG_UPDATED_FROM_ADT : - SwtUpdaterData.TOOLS_MSG_UPDATED_FROM_SDKMAN); - needsRefresh = installed != null && !installed.isEmpty(); - } finally { - endOperationPending(); - - if (needsRefresh) { - // The local package list has changed, make sure to refresh it - mImpl.localReload(); + //notify listeners something was installed, so that they can refresh + //reloadSdk(); } } + } finally { + endOperationPending(); + + if (needsRefresh) { + // The local package list has changed, make sure to refresh it + startLoadPackages(); + } } } /** - * Selects the archives that can be installed. - * This can be used with a null {@code outArchives} just to count the number of - * installable archives. + * Selects the packages that can be installed. + * This can be used with a null {@code outPackageItems} just to count the number of + * installable packages. * - * @param outArchives An archive list where to add the archives that can be installed. + * @param outPackageItems A package item list to return remote packages. * This can be null. * @return The number of archives that can be installed. */ - private int getArchivesForInstall(List outArchives) { + private int getPackagesForInstall(List outPackageItems) { if (mTreeViewer == null || - mTreeViewer.getTree() == null || - mTreeViewer.getTree().isDisposed()) { + mTreeViewer.getTree() == null || + mTreeViewer.getTree().isDisposed()) { return 0; } Object[] checked = mTreeViewer.getCheckedElements(); if (checked == null) { return 0; } - int count = 0; - - // Give us a way to force install of incompatible archives. - boolean checkIsCompatible = - System.getenv(ArchiveInstaller.ENV_VAR_IGNORE_COMPAT) == null; - - if (mDisplayArchives) { - // In detail mode, we display archives so we can install only the - // archives that are actually selected. - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add((Archive) c); - } - } - } - } - } else { - // In non-detail mode, we install all the compatible archives - // found in the selected pkg items. We also automatically - // select update packages rather than the root package if any. - - for (Object c : checked) { - Package p = null; - if (c instanceof Package) { - // This is an update package - p = (Package) c; - } else if (c instanceof PkgItem) { - p = ((PkgItem) c).getMainPackage(); - - PkgItem pi = (PkgItem) c; - if (pi.getState() == PkgState.INSTALLED) { - // We don't allow installing items that are already installed - // unless they have a pending update. - p = pi.getUpdatePkg(); - - } else if (pi.getState() == PkgState.NEW) { - p = pi.getMainPackage(); - } + for (Object c : checked) { + if (c instanceof PkgItem) { + PkgItem packageItem = (PkgItem)c; + RemotePackage remotePackage = null; + if (packageItem.hasUpdatePkg()) { + remotePackage = packageItem.getUpdatePkg().getRemote(); + } else if (packageItem.getState() == PkgState.NEW) { + remotePackage = (RemotePackage) packageItem.getMainPackage(); } - if (p != null) { - for (Archive a : p.getArchives()) { - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add(a); - } - } + if (remotePackage != null) { + count++; + if (outPackageItems != null) { + outPackageItems.add(packageItem); } } } } - return count; } @@ -1057,29 +1025,38 @@ private void onButtonDelete() { final String title = "Delete SDK Package"; StringBuilder msg = new StringBuilder("Are you sure you want to delete:"); - // A list of archives to delete - final ArrayList archives = new ArrayList(); + // A list of package items to delete + final ArrayList outPackageItems = new ArrayList(); - getArchivesToDelete(msg, archives); + getArchivesToDelete(msg, outPackageItems); - if (!archives.isEmpty()) { + if (!outPackageItems.isEmpty()) { msg.append("\n").append("This cannot be undone."); //$NON-NLS-1$ if (MessageDialog.openQuestion(getShell(), title, msg.toString())) { try { beginOperationPending(); - mImpl.mSwtUpdaterData.getTaskFactory().start("Delete Package", new ITask() { + mTaskFactory.start("Delete Package", new ITask() { @Override public void run(ITaskMonitor monitor) { - monitor.setProgressMax(archives.size() + 1); - for (Archive a : archives) { + monitor.setProgressMax(outPackageItems.size() + 1); + for (PkgItem packageItem : outPackageItems) { + LocalPackage localPackage = (LocalPackage)packageItem.getMainPackage(); monitor.setDescription("Deleting '%1$s' (%2$s)", - a.getParentPackage().getShortDescription(), - a.getLocalOsPath()); + localPackage.getDisplayName(), + localPackage.getPath()); // Delete the actual package - a.deleteLocal(); - + Uninstaller uninstaller = SdkInstallerUtil.findBestInstallerFactory(localPackage, mSdkContext.getHandler()) + .createUninstaller(localPackage, mSdkContext.getRepoManager(), mSdkContext.getFileOp()); + if (applyPackageOperation(uninstaller)) { + packageItem.markDeleted(); + } else { + // there was an error, abort. + monitor.error(null, "Uninstall of package failed due to an error"); + monitor.setProgressMax(0); + break; + } monitor.incProgress(1); if (monitor.isCancelRequested()) { break; @@ -1088,18 +1065,26 @@ public void run(ITaskMonitor monitor) { monitor.incProgress(1); monitor.setDescription("Done"); + mPackageAnalyser.removeDeletedNodes(); } }); } finally { endOperationPending(); // The local package list has changed, make sure to refresh it - mImpl.localReload(); + startLoadPackages(); } - } + } } } + + private boolean applyPackageOperation( + @NonNull PackageOperation operation) { + ProgressIndicator progressIndicator = mSdkContext.getProgressIndicator(); + return operation.prepare(progressIndicator) && operation.complete(progressIndicator); + } + /** * Selects the archives that can be deleted and collect their names. * This can be used with a null {@code outArchives} and a null {@code outMsg} @@ -1107,11 +1092,11 @@ public void run(ITaskMonitor monitor) { * * @param outMsg A StringBuilder where the names of the packages to be deleted is * accumulated. This is used to confirm deletion with the user. - * @param outArchives An archive list where to add the archives that can be installed. + * @param outPackageItems A package item list to return local packages * This can be null. * @return The number of archives that can be deleted. */ - private int getArchivesToDelete(StringBuilder outMsg, List outArchives) { + private int getArchivesToDelete(StringBuilder outMsg, List outPackageItems) { if (mTreeViewer == null || mTreeViewer.getTree() == null || mTreeViewer.getTree().isDisposed()) { @@ -1124,92 +1109,43 @@ private int getArchivesToDelete(StringBuilder outMsg, List outArchives) } int count = 0; - - if (mDisplayArchives) { - // In detail mode, select archives that can be deleted - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - Package p = a.getParentPackage(); - if (p != null && dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); + for (Object c : checked) { + if (c instanceof PkgItem) { + PkgItem packageItem = (PkgItem) c; + PkgState state = packageItem.getState(); + if (state == PkgState.INSTALLED) { + LocalPackage localPackage = (LocalPackage)packageItem.getMainPackage(); + count++; + if (outMsg != null) { + File dir = new File(localPackage.getPath()); + if (dir.isDirectory()) { + outMsg.append("\n - ") //$NON-NLS-1$ + .append(localPackage.getDisplayName()); } } - } - } - } else { - // In non-detail mode, select archives of selected packages that can be deleted. - - for (Object c : checked) { - if (c instanceof PkgItem) { - PkgItem pi = (PkgItem) c; - PkgState state = pi.getState(); - if (state == PkgState.INSTALLED) { - Package p = pi.getMainPackage(); - - for (Archive a : p.getArchives()) { - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - if (dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); - } - } - } + if (outPackageItems != null) { + outPackageItems.add(packageItem); } } } } - return count; } // ---------------------- - - // --- Implementation of ISdkChangeListener --- - - @Override - public void onSdkLoaded() { - onSdkReload(); - } - - @Override - public void onSdkReload() { - // The sdkmanager finished reloading its data. We must not call localReload() from here - // since we don't want to alter the sdkmanager's data that just finished loading. - mImpl.loadPackages(); + public void onReady(ProgressRunner progressRunner, ILogUiProvider sdkProgressControl, ITaskFactory taskFactory) { + mProgressRunner = progressRunner; + mSdkProgressControl = sdkProgressControl; + mTaskFactory = taskFactory; + startLoadPackages(); } - @Override - public void preInstallHook() { - // nothing to be done for now. - } - @Override - public void postInstallHook() { - // nothing to be done for now. + public void onSdkReload() { + startLoadPackages(); } - // --- End of hiding from SWT Designer --- //$hide<<$ } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java deleted file mode 100644 index 71f990e6..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (C) 2012 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.sdkuilib.internal.repository.ui; - -import com.android.SdkConstants; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.DownloadCache.Strategy; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.updater.PackageLoader; -import com.android.sdklib.internal.repository.updater.PackageLoader.ISourceLoadedCallback; -import com.android.sdklib.internal.repository.updater.PkgItem; -import com.android.sdklib.internal.repository.updater.PkgItem.PkgState; -import com.android.sdklib.repository.IDescription; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.core.PackagesDiffLogic; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgCategoryApi; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IInputProvider; -import org.eclipse.jface.viewers.ITableFontProvider; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; - -/** - * Base class for {@link PackagesPage} that holds most of the logic to display - * the tree/list of packages. This class holds most of the logic and {@link PackagesPage} - * holds most of the UI (creating the UI, dealing with menus and buttons and tree - * selection.) This makes it easier to test the functionality by mocking only a - * subset of the UI. - */ -abstract class PackagesPageImpl { - - final SwtUpdaterData mSwtUpdaterData; - final PackagesDiffLogic mDiffLogic; - - private ICheckboxTreeViewer mITreeViewer; - private ITreeViewerColumn mIColumnName; - private ITreeViewerColumn mIColumnApi; - private ITreeViewerColumn mIColumnRevision; - private ITreeViewerColumn mIColumnStatus; - - PackagesPageImpl(SwtUpdaterData swtUpdaterData) { - mSwtUpdaterData = swtUpdaterData; - mDiffLogic = new PackagesDiffLogic(swtUpdaterData); - } - - /** - * Utility method that derived classes can override to check whether the UI is disposed. - * When the UI is disposed, most operations that affect the UI will be bypassed. - * @return True if UI is not available and should not be touched. - */ - abstract protected boolean isUiDisposed(); - - /** - * Utility method to execute a runnable on the main UI thread. - * Will do nothing if {@link #isUiDisposed()} returns false. - * @param runnable The runnable to execute on the main UI thread. - */ - abstract protected void syncExec(Runnable runnable); - - /** - * Synchronizes the 'checked' state of PkgItems in the tree with their internal isChecked state. - */ - abstract protected void syncViewerSelection(); - - void performFirstLoad() { - // First a package loader is created that only checks - // the local cache xml files. It populates the package - // list based on what the client got last, essentially. - loadPackages(true /*useLocalCache*/, false /*overrideExisting*/); - - // Next a regular package loader is created that will - // respect the expiration and refresh parameters of the - // download cache. - loadPackages(false /*useLocalCache*/, true /*overrideExisting*/); - } - - public void setITreeViewer(ICheckboxTreeViewer iTreeViewer) { - mITreeViewer = iTreeViewer; - } - - public void setIColumns( - ITreeViewerColumn columnName, - ITreeViewerColumn columnApi, - ITreeViewerColumn columnRevision, - ITreeViewerColumn columnStatus) { - mIColumnName = columnName; - mIColumnApi = columnApi; - mIColumnRevision = columnRevision; - mIColumnStatus = columnStatus; - } - - void postCreate() { - // Caller needs to call setITreeViewer before this. - assert mITreeViewer != null; - // Caller needs to call setIColumns before this. - assert mIColumnApi != null; - assert mIColumnName != null; - assert mIColumnStatus != null; - assert mIColumnRevision != null; - - mITreeViewer.setContentProvider(new PkgContentProvider(mITreeViewer)); - - mIColumnApi.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnApi))); - mIColumnName.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnName))); - mIColumnStatus.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnStatus))); - mIColumnRevision.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnRevision))); - } - - /** - * Performs a full reload by removing all cached packages data, including the platforms - * and addons from the sdkmanager instance. This will perform a full local parsing - * as well as a full reload of the remote data (by fetching all sources again.) - */ - void fullReload() { - // Clear all source information, forcing them to be refreshed. - mSwtUpdaterData.getSources().clearAllPackages(); - // Clear and reload all local data too. - localReload(); - } - - /** - * Performs a full reload of all the local package information, including the platforms - * and addons from the sdkmanager instance. This will perform a full local parsing. - *

- * This method does NOT force a new fetch of the remote sources. - * - * @see #fullReload() - */ - void localReload() { - // Clear all source caches, otherwise loading will use the cached data - mSwtUpdaterData.getLocalSdkParser().clearPackages(); - mSwtUpdaterData.getSdkManager().reloadSdk(mSwtUpdaterData.getSdkLog()); - loadPackages(); - } - - /** - * Performs a "normal" reload of the package information, use the default download - * cache and refreshing strategy as needed. - */ - void loadPackages() { - loadPackages(false /*useLocalCache*/, false /*overrideExisting*/); - } - - /** - * Performs a reload of the package information. - * - * @param useLocalCache When true, the {@link PackageLoader} is switched to use - * a specific {@link DownloadCache} using the {@link Strategy#ONLY_CACHE}, meaning - * it will only use data from the local cache. It will not try to fetch or refresh - * manifests. This is used once the very first time the sdk manager window opens - * and is typically followed by a regular load with refresh. - */ - abstract protected void loadPackages(boolean useLocalCache, boolean overrideExisting); - - /** - * Actual implementation of {@link #loadPackages(boolean, boolean)}. - * Derived implementations must call this to do the actual work after setting up the UI. - */ - void loadPackagesImpl(final boolean useLocalCache, final boolean overrideExisting) { - if (mSwtUpdaterData == null) { - return; - } - - PackageLoader packageLoader = getPackageLoader(useLocalCache); - assert packageLoader != null; - - mDiffLogic.updateStart(); - packageLoader.loadPackages(overrideExisting, new ISourceLoadedCallback() { - @Override - public boolean onUpdateSource(SdkSource source, Package[] newPackages) { - // This runs in a thread and must not access UI directly. - final boolean changed = mDiffLogic.updateSourcePackages(source, newPackages); - - syncExec(new Runnable() { - @Override - public void run() { - if (changed || - mITreeViewer.getInput() != mDiffLogic.getCategories()) { - refreshViewerInput(); - } - } - }); - - // Return true to tell the loader to continue with the next source. - // Return false to stop the loader if any UI has been disposed, which can - // happen if the user is trying to close the window during the load operation. - return !isUiDisposed(); - } - - @Override - public void onLoadCompleted() { - // This runs in a thread and must not access UI directly. - final boolean changed = mDiffLogic.updateEnd(); - - syncExec(new Runnable() { - @Override - public void run() { - if (changed || - mITreeViewer.getInput() != mDiffLogic.getCategories()) { - try { - refreshViewerInput(); - } catch (Exception ignore) {} - } - - if (!useLocalCache && - mDiffLogic.isFirstLoadComplete() && - !isUiDisposed()) { - // At the end of the first load, if nothing is selected then - // automatically select all new and update packages. - Object[] checked = mITreeViewer.getCheckedElements(); - if (checked == null || checked.length == 0) { - onSelectNewUpdates( - false, //selectNew - true, //selectUpdates, - true); //selectTop - } - } - } - }); - } - }); - } - - /** - * Used by {@link #loadPackagesImpl(boolean, boolean)} to get the package - * loader for the first or second pass update. When starting the manager - * starts with a first pass that reads only from the local cache, with no - * extra network access. That's {@code useLocalCache} being true. - *

- * Leter it does a second pass with {@code useLocalCache} set to false - * and actually uses the download cache specified in {@link SwtUpdaterData}. - * - * This is extracted so that we can control this cache via unit tests. - */ - protected PackageLoader getPackageLoader(boolean useLocalCache) { - if (useLocalCache) { - return new PackageLoader(mSwtUpdaterData, new DownloadCache(Strategy.ONLY_CACHE)); - } else { - return mSwtUpdaterData.getPackageLoader(); - } - } - - /** - * Overridden by the UI to respond to a request to refresh the tree viewer - * when the input has changed. - * The implementation must call {@link #setViewerInput()} somehow and will - * also need to adjust the expand state of the tree items and/or update - * some buttons or other state. - */ - abstract protected void refreshViewerInput(); - - /** - * Invoked from {@link #refreshViewerInput()} to actually either set the - * input of the tree viewer or refresh it if it's the same input - * object. - */ - protected void setViewerInput() { - List cats = mDiffLogic.getCategories(); - if (mITreeViewer.getInput() != cats) { - // set initial input - mITreeViewer.setInput(cats); - } else { - // refresh existing, which preserves the expanded state, the selection - // and the checked state. - mITreeViewer.refresh(); - } - } - - /** - * Checks all PkgItems that are either new or have updates or select top platform - * for initial run. - */ - void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { - // This does not update the tree itself, syncViewerSelection does it in the caller. - mDiffLogic.checkNewUpdateItems( - selectNew, - selectUpdates, - selectTop, - SdkConstants.CURRENT_PLATFORM); - syncViewerSelection(); - } - - /** - * Deselect all checked PkgItems. - */ - void onDeselectAll() { - // This does not update the tree itself, syncViewerSelection does it in the caller. - mDiffLogic.uncheckAllItems(); - } - - // ---------------------- - - abstract protected Font getTreeFontItalic(); - - class PkgCellLabelProvider extends ColumnLabelProvider implements ITableFontProvider { - - private final ITreeViewerColumn mColumn; - - public PkgCellLabelProvider(ITreeViewerColumn column) { - super(); - mColumn = column; - } - - @Override - public String getText(Object element) { - - if (mColumn == mIColumnName) { - if (element instanceof PkgCategory) { - return ((PkgCategory) element).getLabel(); - } else if (element instanceof PkgItem) { - return getPkgItemName((PkgItem) element); - } else if (element instanceof IDescription) { - return ((IDescription) element).getShortDescription(); - } - - } else if (mColumn == mIColumnApi) { - AndroidVersion version = null; - if (element instanceof PkgItem) { - version = ((PkgItem) element).getAndroidVersion(); - } - if (version != null) { - return version.getApiString(); - } - - } else if (mColumn == mIColumnRevision) { - if (element instanceof PkgItem) { - PkgItem pkg = (PkgItem) element; - return pkg.getRevision().toShortString(); - } - - } else if (mColumn == mIColumnStatus) { - if (element instanceof PkgItem) { - PkgItem pkg = (PkgItem) element; - - switch(pkg.getState()) { - case INSTALLED: - Package update = pkg.getUpdatePkg(); - if (update != null) { - return String.format( - "Update available: rev. %1$s", - update.getRevision().toShortString()); - } - return "Installed"; - - case NEW: - Package p = pkg.getMainPackage(); - if (p != null && p.hasCompatibleArchive()) { - return "Not installed"; - } else { - return String.format("Not compatible with %1$s", - SdkConstants.currentPlatformName()); - } - } - return pkg.getState().toString(); - - } else if (element instanceof Package) { - // This is an update package. - return "New revision " + ((Package) element).getRevision().toShortString(); - } - } - - return ""; //$NON-NLS-1$ - } - - private String getPkgItemName(PkgItem item) { - String name = item.getName().trim(); - - // When sorting by API, the package name might contains the API number - // or the platform name at the end. If we find it, cut it out since it's - // redundant. - - PkgCategoryApi cat = (PkgCategoryApi) findCategoryForItem(item); - String apiLabel = cat.getApiLabel(); - String platLabel = cat.getPlatformName(); - - if (platLabel != null && name.endsWith(platLabel)) { - return name.substring(0, name.length() - platLabel.length()); - - } else if (apiLabel != null && name.endsWith(apiLabel)) { - return name.substring(0, name.length() - apiLabel.length()); - - } else if (platLabel != null && item.isObsolete() && name.indexOf(platLabel) > 0) { - // For obsolete items, the format is " (Obsolete)" - // so in this case only accept removing a platform name that is not at - // the end. - name = name.replace(platLabel, ""); //$NON-NLS-1$ - } - - // Collapse potential duplicated spacing - name = name.replaceAll(" +", " "); //$NON-NLS-1$ //$NON-NLS-2$ - - return name; - } - - private PkgCategory findCategoryForItem(PkgItem item) { - List cats = mDiffLogic.getCategories(); - for (PkgCategory cat : cats) { - for (PkgItem i : cat.getItems()) { - if (i == item) { - return cat; - } - } - } - - return null; - } - - @Override - public Image getImage(Object element) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); - - if (imgFactory != null) { - if (mColumn == mIColumnName) { - if (element instanceof PkgCategory) { - return imgFactory.getImageForObject(((PkgCategory) element).getIconRef()); - } else if (element instanceof PkgItem) { - return imgFactory.getImageForObject(((PkgItem) element).getMainPackage()); - } - return imgFactory.getImageForObject(element); - - } else if (mColumn == mIColumnStatus && element instanceof PkgItem) { - PkgItem pi = (PkgItem) element; - switch(pi.getState()) { - case INSTALLED: - if (pi.hasUpdatePkg()) { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_UPDATE); - } else { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INSTALLED); - } - case NEW: - Package p = pi.getMainPackage(); - if (p != null && p.hasCompatibleArchive()) { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_NEW); - } else { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INCOMPAT); - } - } - } - } - return super.getImage(element); - } - - // -- ITableFontProvider - - @Override - public Font getFont(Object element, int columnIndex) { - if (element instanceof PkgItem) { - if (((PkgItem) element).getState() == PkgState.NEW) { - return getTreeFontItalic(); - } - } else if (element instanceof Package) { - // update package - return getTreeFontItalic(); - } - return super.getFont(element); - } - - // -- Tooltip support - - @Override - public String getToolTipText(Object element) { - PkgItem pi = element instanceof PkgItem ? (PkgItem) element : null; - if (pi != null) { - element = pi.getMainPackage(); - } - if (element instanceof IDescription) { - String s = getTooltipDescription((IDescription) element); - - if (pi != null && pi.hasUpdatePkg()) { - s += "\n-----------------" + //$NON-NLS-1$ - "\nUpdate Available:\n" + //$NON-NLS-1$ - getTooltipDescription(pi.getUpdatePkg()); - } - - return s; - } - return super.getToolTipText(element); - } - - private String getTooltipDescription(IDescription element) { - String s = element.getLongDescription(); - if (element instanceof Package) { - Package p = (Package) element; - - if (!p.isLocal()) { - // For non-installed item, try to find a download size - for (Archive a : p.getArchives()) { - if (!a.isLocal() && a.isCompatible()) { - s += '\n' + a.getSizeDescription(); - break; - } - } - } - - // Display info about where this package comes/came from - SdkSource src = p.getParentSource(); - if (src != null) { - try { - URL url = new URL(src.getUrl()); - String host = url.getHost(); - if (p.isLocal()) { - s += String.format("\nInstalled from %1$s", host); - } else { - s += String.format("\nProvided by %1$s", host); - } - } catch (MalformedURLException ignore) { - } - } - } - return s; - } - - @Override - public Point getToolTipShift(Object object) { - return new Point(15, 5); - } - - @Override - public int getToolTipDisplayDelayTime(Object object) { - return 500; - } - } - - interface ICheckboxTreeViewer extends IInputProvider { - void setContentProvider(PkgContentProvider pkgContentProvider); - void refresh(); - void setInput(List cats); - Object[] getCheckedElements(); - } - - interface ITreeViewerColumn { - void setLabelProvider(ColumnLabelProvider labelProvider); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkProgressFactory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkProgressFactory.java new file mode 100644 index 00000000..52394419 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkProgressFactory.java @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.repository.ui; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.repository.api.ProgressIndicator; +import com.android.repository.api.ProgressIndicatorAdapter; +import com.android.repository.api.ProgressRunner; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskFactory; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.tasks.ILogUiProvider; +import com.android.sdkuilib.internal.tasks.ProgressTask; +import com.android.sdkuilib.internal.tasks.ProgressView; +import com.android.sdkuilib.internal.tasks.SdkProgressIndicator; +import com.android.utils.ILogger; + +/** + * An {@link ITaskFactory} that creates a new {@link ProgressTask} dialog + * for each new task. + */ +public class SdkProgressFactory extends ProgressIndicatorAdapter implements ITaskFactory, ILogger, ProgressRunner { + + public interface ISdkLogWindow + { + void log(String log); + void logVerbose(String log); + void logError(String log); + void setDescription(String description); + void show(); + } + + private final ProgressView progressView; + private final ISdkLogWindow logWindow; + private final ProgressBar progressBar; + private int referenceCount; + + /** + * Creates a new {@link ProgressView} object, a simple "holder" for the various + * widgets used to display and update a progress + status bar. This object is + * provided to the factory. + * + * @param statusText The label to display titles of status updates (e.g. task titles and + * calls to {@link #setDescription(String)}.) Must not be null. + * @param progressBar The progress bar to update during a task. Must not be null. + * @param stopButton The stop button. It will be disabled when there's no task that can + * be interrupted. A selection listener will be attached to it. Optional. Can be null. + * @param logWindow Log adapter which can be requested to become visible when errors are logged + */ + public SdkProgressFactory( + Label statusText, + ProgressBar progressBar, + Control stopButton, + ISdkLogWindow logWindow) { + this.logWindow = logWindow; + this.progressBar = progressBar; + this.progressView = new ProgressView(statusText, progressBar, stopButton, getLogUiProvider(logWindow)); + } + + public ILogUiProvider getProgressControl() + { + return progressView; + } + + @Override + public void start(String title, ITask task) { + start(title, null /*monitor*/, task); + } + + @Override + public void start(String title, ITaskMonitor parentMonitor, ITask task) { + progressView.startTask(title, parentMonitor, task, true); + } + + // Returns object which delegates all logging to the logWindow window + // and filters errors to make sure the window is visible when + // an error is logged. + private ILogUiProvider getLogUiProvider(ISdkLogWindow logWindow) + { + return new ILogUiProvider() { + @Override + public void setDescription(String description) { + logWindow.setDescription(description); + } + + @Override + public void log(String log) { + logWindow.log(log); + } + + @Override + public void logVerbose(String log) { + logWindow.logVerbose(log); + } + + @Override + public void logError(String log) { + logWindow.logError(log); + logWindow.show(); + }}; + } + + // --- ILogger interface ---- // + @Override + public void error(Throwable throwable, String errorFormat, Object... arg) { + StringWriter builder = new StringWriter(); + if (errorFormat != null) + builder.append(String.format("Error: " + errorFormat, arg)); + + if (throwable != null) { + if (errorFormat == null) + builder.append("Error: ").append(throwable.getMessage()); + builder.append("\n"); + PrintWriter writer = new PrintWriter(builder); + throwable.printStackTrace(writer); + } + logWindow.logError(builder.toString()); + logWindow.show(); + } + + + @Override + public void info(String errorFormat, Object... arg) { + logWindow.log(String.format(errorFormat, arg)); + } + + + @Override + public void verbose(String errorFormat, Object... arg) { + logWindow.logVerbose(String.format(errorFormat, arg)); + } + + + @Override + public void warning(String errorFormat, Object... arg) { + // TODO - Add warning level + logWindow.log(String.format(errorFormat, arg)); + } + + // --- Logger component of IProgressIndicator interface ---- // + /** + * Logs a warning. + */ + @Override + public void logWarning(@NonNull String s) { + logWindow.log(s); + } + + /** + * Logs a warning, including a stacktrace. + */ + @Override + public void logWarning(@NonNull String s, @Nullable Throwable throwable) { + StringWriter builder = new StringWriter(); + builder.append(s); + if (throwable != null) { + builder.append("\n"); + PrintWriter writer = new PrintWriter(builder); + throwable.printStackTrace(writer); + } + logWindow.log(builder.toString()); + } + + /** + * Logs an error. + */ + @Override + public void logError(@NonNull String s) { + error(null, s); + } + + /** + * Logs an error, including a stacktrace. + */ + @Override + public void logError(@NonNull String s, @Nullable Throwable throwable) { + error(throwable, s); + } + + /** + * Logs an info message. + */ + @Override + public void logInfo(@NonNull String s) { + logWindow.log(s); + } + + @Override + public void logVerbose(@NonNull String s) { + logWindow.logVerbose(s); + } + + + @Override + public void runAsyncWithProgress(final ProgressRunnable progressRunnable) { + String title = this.getClass().getSimpleName(); + ProgressRunnable monitor = new ProgressRunnable(){ + + @Override + public void run(ProgressIndicator indicator, ProgressRunner runner) { + try + { + progressRunnable.run(indicator, runner); + } + finally + { + progressView.endTask(); + } + }}; + + Runnable runnable = new Runnable(){ + + @Override + public void run() { + progressView.startTask(title, null, taskInstance(monitor), false); + }}; + final Thread t = new Thread(runnable , title + "_async_thread_ " + referenceCount++); + t.start(); + } + + + @Override + public void runSyncWithProgress(ProgressRunnable progressRunnable) { + start("", taskInstance(progressRunnable)); + } + + + @Override + public void runSyncWithoutProgress(Runnable runnable) { + runnable.run(); + } + + private ITask taskInstance(ProgressRunnable progressRunnable) + { + return new ITask(){ + + @Override + public void run(ITaskMonitor monitor) { + ProgressIndicator progressIndicator = new SdkProgressIndicator(monitor); + ProgressRunner progressRunner = new ProgressRunner(){ + + @Override + public void runAsyncWithProgress(ProgressRunnable r) { + if (!progressIndicator.isCanceled()) + SdkProgressFactory.this.runAsyncWithProgress(r); + } + + @Override + public void runSyncWithProgress(ProgressRunnable r) { + if (!progressIndicator.isCanceled()) + SdkProgressFactory.this.runSyncWithProgress(r); + } + + @Override + public void runSyncWithoutProgress(Runnable r) { + if (!progressIndicator.isCanceled()) + SdkProgressFactory.this.runSyncWithoutProgress(r); + }}; + progressRunnable.run(progressIndicator, progressRunner); + } + }; + + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterChooserDialog.java similarity index 67% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterChooserDialog.java index 002011ba..60fc8905 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterChooserDialog.java @@ -14,23 +14,22 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.repository; +package com.android.sdkuilib.internal.repository.ui; -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.updater.ArchiveInfo; -import com.android.sdklib.internal.repository.updater.SdkUpdaterLogic; -import com.android.sdklib.repository.FullRevision; -import com.android.sdklib.repository.License; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDialog; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import org.eclipse.andmore.sdktool.SdkContext; +import org.eclipse.andmore.sdktool.Utilities; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; @@ -62,13 +61,19 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; +import com.android.SdkConstants; +import com.android.annotations.NonNull; +import com.android.repository.api.License; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepositorySource; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.util.InstallerUtil; +import com.android.sdklib.AndroidVersion; +import com.android.sdkuilib.internal.repository.PackageInfo; +import com.android.sdkuilib.internal.repository.content.PackageAnalyser; +import org.eclipse.andmore.base.resources.ImageFactory; +import com.android.sdkuilib.ui.GridDialog; /** @@ -93,10 +98,13 @@ final class SdkUpdaterChooserDialog extends GridDialog { private Button mLicenseRadioReject; private Button mLicenseRadioAcceptLicense; private Group mPackageTextGroup; - private final SwtUpdaterData mSwtUpdaterData; private Group mTableGroup; private Label mErrorLabel; + private Set unacceptedLicenses = new HashSet<>(); + //private Multimap unacceptedLicenses = HashMultimap.create(); + //private List acceptedPackages = new ArrayList<>(); + private final SdkContext mSdkContext; /** * List of all archives to be installed with dependency information. *

@@ -105,9 +113,9 @@ final class SdkUpdaterChooserDialog extends GridDialog { * limited number of archives to deal with (e.g. < 10 now). We might want to revisit * this later if it becomes an issue. Right now just do the simple thing. *

- * Typically we could add a map Archive=>ArchiveInfo later. + * Typically we could add a map Package=>PackageInfo later. */ - private final Collection mArchives; + private final List mPackages = new ArrayList<>(); @@ -115,41 +123,40 @@ final class SdkUpdaterChooserDialog extends GridDialog { * Create the dialog. * * @param parentShell The shell to use, typically updaterData.getWindowShell() - * @param swtUpdaterData The updater data - * @param archives The archives to be installed + * @param SdkContext The updater data + * @param packages The packages to be installed */ public SdkUpdaterChooserDialog(Shell parentShell, - SwtUpdaterData swtUpdaterData, - Collection archives) { + SdkContext SdkContext, + Collection updates, + List newPackages) { super(parentShell, 3, false/*makeColumnsEqual*/); - mSwtUpdaterData = swtUpdaterData; - mArchives = archives; + mSdkContext = SdkContext; + init(updates); + init(newPackages); } - @Override + @Override protected boolean isResizable() { return true; } /** - * Returns the results, i.e. the list of selected new archives to install. - * This is similar to the {@link ArchiveInfo} list instance given to the constructor - * except only accepted archives are present. + * Returns the results, i.e. the list of selected new packages to install. *

* An empty list is returned if cancel was chosen. */ - public ArrayList getResult() { - ArrayList ais = new ArrayList(); + public ArrayList getResult() { + ArrayList packageList = new ArrayList(); if (getReturnCode() == Window.OK) { - for (ArchiveInfo ai : mArchives) { - if (ai.isAccepted()) { - ais.add(ai); + for (PackageInfo packageInfo : mPackages) { + if (packageInfo.isAccepted()) { + packageList.add(packageInfo.getNewPackage()); } } } - - return ais; + return packageList; } /** @@ -314,32 +321,29 @@ protected Control createButtonBar(Composite parent) { @Override public void create() { super.create(); - // set window title getShell().setText("Choose Packages to Install"); - setWindowImage(); - - // Automatically accept those with an empty license or no license - for (ArchiveInfo ai : mArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - License license = a.getParentPackage().getLicense(); - boolean hasLicense = license != null && - license.getLicense() != null && - license.getLicense().length() > 0; - ai.setAccepted(!hasLicense); + // Automatically accept those with no license + for (PackageInfo packageInfo : mPackages) { + RemotePackage remote = packageInfo.getNewPackage(); + License license = remote.getLicense(); + if (license == null) + packageInfo.setAccepted(true); + else { + boolean hasLicense = license.checkAccepted(mSdkContext.getLocation(), mSdkContext.getFileOp()); + if (hasLicense) + packageInfo.setAccepted(true); + else + unacceptedLicenses.add(remote); } } - // Fill the list with the replacement packages - mTreeViewPackage.setLabelProvider(new NewArchivesLabelProvider()); - mTreeViewPackage.setContentProvider(new NewArchivesContentProvider()); - mTreeViewPackage.setInput(createTreeInput(mArchives)); + mTreeViewPackage.setLabelProvider(new NewPackagesLabelProvider()); + mTreeViewPackage.setContentProvider(new NewPackagesContentProvider()); + mTreeViewPackage.setInput(createTreeInput(mPackages)); mTreeViewPackage.expandAll(); - adjustColumnsWidth(); - // select first item onPackageSelected(); } @@ -353,8 +357,8 @@ private void setWindowImage() { imageName = "android_icon_128.png"; //$NON-NLS-1$ } - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { getShell().setImage(imgFactory.getImageByName(imageName)); } @@ -414,21 +418,21 @@ private void onPackageSelected() { Object item = getSelectedItem(); // Update mAcceptSameAllLicense : true if all items under the same license are accepted. - ArchiveInfo ai = null; - List list = null; - if (item instanceof ArchiveInfo) { - ai = (ArchiveInfo) item; + PackageInfo packageInfo = null; + List list = null; + if (item instanceof PackageInfo) { + packageInfo = (PackageInfo) item; Object p = - ((NewArchivesContentProvider) mTreeViewPackage.getContentProvider()).getParent(ai); + ((NewPackagesContentProvider) mTreeViewPackage.getContentProvider()).getParent(packageInfo); if (p instanceof LicenseEntry) { - list = ((LicenseEntry) p).getArchives(); + list = ((LicenseEntry) p).getPackageInfoList(); } - displayPackageInformation(ai); + displayPackageInformation(packageInfo); } else if (item instanceof LicenseEntry) { LicenseEntry entry = (LicenseEntry) item; - list = entry.getArchives(); + list = entry.getPackageInfoList(); displayLicenseInformation(entry); } else { @@ -441,10 +445,10 @@ private void onPackageSelected() { mAcceptSameAllLicense = list != null && list.size() > 0; if (mAcceptSameAllLicense) { assert list != null; - License lic0 = getLicense(list.get(0)); - for (ArchiveInfo ai2 : list) { - License lic2 = getLicense(ai2); - if (ai2.isAccepted() && (lic0 == lic2 || lic0.equals(lic2))) { + License lic0 = list.get(0).getNewPackage().getLicense(); + for (PackageInfo packageInfo2 : list) { + License lic2 = packageInfo2.getNewPackage().getLicense(); + if (packageInfo2.isAccepted() && (lic0 == lic2 || lic0.equals(lic2))) { continue; } else { mAcceptSameAllLicense = false; @@ -453,17 +457,17 @@ private void onPackageSelected() { } } - displayMissingDependency(ai); - updateLicenceRadios(ai); + displayMissingDependency(packageInfo); + updateLicenceRadios(packageInfo); } /** Returns the currently selected tree item. - * @return Either {@link ArchiveInfo} or {@link LicenseEntry} or null. */ + * @return Either {@link PackageInfo} or {@link LicenseEntry} or null. */ private Object getSelectedItem() { ISelection sel = mTreeViewPackage.getSelection(); if (sel instanceof IStructuredSelection) { Object elem = ((IStructuredSelection) sel).getFirstElement(); - if (elem instanceof ArchiveInfo || elem instanceof LicenseEntry) { + if (elem instanceof PackageInfo || elem instanceof LicenseEntry) { return elem; } } @@ -483,94 +487,74 @@ private void displayEmptyInformation() { * Note that right now there is no logic to support more than one level of dependencies * (e.g. A <- B <- C and A is disabled so C should be disabled; currently C's state depends * solely on B's state). We currently don't need this. It would be straightforward to add - * if we had a need for it, though. This would require changes to {@link ArchiveInfo} and + * if we had a need for it, though. This would require changes to {@link PackageInfo} and * {@link SdkUpdaterLogic}. */ - private void displayPackageInformation(ArchiveInfo ai) { - Archive aNew = ai == null ? null : ai.getNewArchive(); - Package pNew = aNew == null ? null : aNew.getParentPackage(); - - if (pNew == null) { - displayEmptyInformation(); - return; - } - assert ai != null; // make Eclipse null detector happy - assert aNew != null; - + private void displayPackageInformation(PackageInfo packageInfo) { mPackageText.setText(""); //$NON-NLS-1$ - addSectionTitle("Package Description\n"); - addText(pNew.getLongDescription(), "\n\n"); //$NON-NLS-1$ - - Archive aOld = ai.getReplaced(); - if (aOld != null) { - Package pOld = aOld.getParentPackage(); - - FullRevision rOld = pOld.getRevision(); - FullRevision rNew = pNew.getRevision(); - - boolean showRev = true; - - if (pNew instanceof IAndroidVersionProvider && - pOld instanceof IAndroidVersionProvider) { - AndroidVersion vOld = ((IAndroidVersionProvider) pOld).getAndroidVersion(); - AndroidVersion vNew = ((IAndroidVersionProvider) pNew).getAndroidVersion(); - - if (!vOld.equals(vNew)) { - // Versions are different, so indicate more than just the revision. - addText(String.format("This update will replace API %1$s revision %2$s with API %3$s revision %4$s.\n\n", - vOld.getApiString(), rOld.toShortString(), - vNew.getApiString(), rNew.toShortString())); - showRev = false; - } + RemotePackage remotePackage = packageInfo.getNewPackage(); + addText(remotePackage.getDisplayName(), "\n\n"); //$NON-NLS-1$ + + LocalPackage localPackage = packageInfo.getReplaced(); + if (localPackage != null) { + AndroidVersion vOld = PackageAnalyser.getAndroidVersion(localPackage); + AndroidVersion vNew = PackageAnalyser.getAndroidVersion(remotePackage); + boolean showRev = (vOld != null) && (vNew != null); + + if (showRev && !vOld.equals(vNew)) { + // Versions are different, so indicate more than just the revision. + addText(String.format("This update will replace API %1$s revision %2$s with API %3$s revision %4$s.\n\n", + vOld.getApiString(), localPackage.getVersion(), + vNew.getApiString(), remotePackage.getVersion())); + showRev = false; } - if (showRev) { addText(String.format("This update will replace revision %1$s with revision %2$s.\n\n", - rOld.toShortString(), - rNew.toShortString())); + localPackage.getVersion(), + remotePackage.getVersion())); } } - - ArchiveInfo[] aDeps = ai.getDependsOn(); - if ((aDeps != null && aDeps.length > 0) || ai.isDependencyFor()) { + List required = InstallerUtil.computeRequiredPackages( + Collections.singletonList(remotePackage), mSdkContext.getPackages(), + mSdkContext.getProgressIndicator()); + if ((required != null && required.size() > 0)) { + // The returned required dependencies includes principal + required.remove(remotePackage); + if ((required.size() > 0)) { addSectionTitle("Dependencies\n"); - - if (aDeps != null && aDeps.length > 0) { - addText("Installing this package also requires installing:"); - for (ArchiveInfo aDep : aDeps) { - addText(String.format("\n- %1$s", - aDep.getShortDescription())); - } - addText("\n\n"); - } - - if (ai.isDependencyFor()) { - addText("This package is a dependency for:"); - for (ArchiveInfo ai2 : ai.getDependenciesFor()) { - addText(String.format("\n- %1$s", - ai2.getShortDescription())); - } - addText("\n\n"); - } + addText("Installing this package also requires installing:"); + for (RemotePackage dependency : required) { + addText(String.format("\n- %1$s", dependency.getDisplayName())); + } + addText("\n\n"); + /* + if (ai.isDependencyFor()) { + addText("This package is a dependency for:"); + for (PackageInfo ai2 : ai.getDependenciesFor()) { + addText(String.format("\n- %1$s", + ai2.getShortDescription())); + } + addText("\n\n"); + } + */ + } } - addSectionTitle("Archive Description\n"); - addText(aNew.getLongDescription(), "\n\n"); //$NON-NLS-1$ + addSectionTitle("Archive Size\n"); + long fileSize = remotePackage.getArchive().getComplete().getSize(); + addText(Utilities.formatFileSize(fileSize), "\n\n"); //$NON-NLS-1$ - License license = pNew.getLicense(); + License license = remotePackage.getLicense(); if (license != null) { - String text = license.getLicense(); - if (text != null) { - addSectionTitle("License\n"); - addText(text.trim(), "\n\n"); //$NON-NLS-1$ - } + addSectionTitle(String.format("License %s:%n", license.getId())); + addText(license.getValue().trim(), "\n\n"); //$NON-NLS-1$ } addSectionTitle("Site\n"); - SdkSource source = pNew.getParentSource(); + RepositorySource source = remotePackage.getSource(); if (source != null) { - addText(source.getShortDescription()); + addText(source.getDisplayName()); } } @@ -578,8 +562,8 @@ private void displayPackageInformation(ArchiveInfo ai) { * Updates the description for a license entry. */ private void displayLicenseInformation(LicenseEntry entry) { - List archives = entry == null ? null : entry.getArchives(); - if (archives == null) { + List packageInfoList = entry == null ? null : entry.getPackageInfoList(); + if (packageInfoList == null) { // There should not be a license entry without any package in it. displayEmptyInformation(); return; @@ -590,105 +574,16 @@ private void displayLicenseInformation(LicenseEntry entry) { License license = null; addSectionTitle("Packages\n"); - for (ArchiveInfo ai : entry.getArchives()) { - Archive aNew = ai.getNewArchive(); - if (aNew != null) { - Package pNew = aNew.getParentPackage(); - if (pNew != null) { - if (license == null) { - license = pNew.getLicense(); - } else { - assert license.equals(pNew.getLicense()); // all items have the same license - } - addText("- ", pNew.getShortDescription(), "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - } - } + for (PackageInfo packageInfo : entry.getPackageInfoList()) { + RemotePackage remote = packageInfo.getNewPackage(); + if (license == null) + license = remote.getLicense(); + addText("- ", remote.getDisplayName(), "\n"); //$NON-NLS-1$ //$NON-NLS-2$ } if (license != null) { - String text = license.getLicense(); - if (text != null) { - addSectionTitle("\nLicense\n"); - addText(text.trim(), "\n\n"); //$NON-NLS-1$ - } - } - } - - /** - * Computes and displays missing dependencies. - * - * If there's a selected package, check the dependency for that one. - * Otherwise display the first missing dependency of any other package. - */ - private void displayMissingDependency(ArchiveInfo ai) { - String error = null; - - try { - if (ai != null) { - if (ai.isAccepted()) { - // Case where this package is accepted but blocked by another non-accepted one - ArchiveInfo[] adeps = ai.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - if (!adep.isAccepted()) { - error = String.format("This package depends on '%1$s'.", - adep.getShortDescription()); - return; - } - } - } - } else { - // Case where this package blocks another one when not accepted - for (ArchiveInfo adep : ai.getDependenciesFor()) { - // It only matters if the blocked one is accepted - if (adep.isAccepted()) { - error = String.format("Package '%1$s' depends on this one.", - adep.getShortDescription()); - return; - } - } - } - } - - // If there is no missing dependency on the current selection, - // just find the first missing dependency of any other package. - for (ArchiveInfo ai2 : mArchives) { - if (ai2 == ai) { - // We already processed that one above. - continue; - } - if (ai2.isAccepted()) { - // The user requested to install this package. - // Check if all its dependencies are met. - ArchiveInfo[] adeps = ai2.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - if (!adep.isAccepted()) { - error = String.format("Package '%1$s' depends on '%2$s'", - ai2.getShortDescription(), - adep.getShortDescription()); - return; - } - } - } - } else { - // The user did not request to install this package. - // Check whether this package blocks another one when not accepted. - for (ArchiveInfo adep : ai2.getDependenciesFor()) { - // It only matters if the blocked one is accepted - // or if it's a local archive that is already installed (these - // are marked as implicitly accepted, so it's the same test.) - if (adep.isAccepted()) { - error = String.format("Package '%1$s' depends on '%2$s'", - adep.getShortDescription(), - ai2.getShortDescription()); - return; - } - } - } - } - } finally { - mErrorLabel.setText(error == null ? "" : error); //$NON-NLS-1$ + addSectionTitle(String.format("License %s:%n", license.getId())); + addText(license.getValue().trim(), "\n\n"); //$NON-NLS-1$ } } @@ -711,7 +606,7 @@ private void addSectionTitle(String string) { mPackageText.setStyleRange(sr); } - private void updateLicenceRadios(ArchiveInfo ai) { + private void updateLicenceRadios(PackageInfo ai) { if (mInternalLicenseRadioUpdate) { return; } @@ -730,16 +625,14 @@ private void updateLicenceRadios(ArchiveInfo ai) { // If the current one isn't, look for another one. boolean missing = mErrorLabel.getText() != null && mErrorLabel.getText().length() > 0; if (!missing && !oneAccepted) { - for(ArchiveInfo ai2 : mArchives) { + for(PackageInfo ai2 : mPackages) { if (ai2.isAccepted()) { oneAccepted = true; break; } } } - getButton(IDialogConstants.OK_ID).setEnabled(!missing && oneAccepted); - mInternalLicenseRadioUpdate = false; } @@ -756,43 +649,44 @@ private void onLicenseRadioSelected() { mInternalLicenseRadioUpdate = true; Object item = getSelectedItem(); - ArchiveInfo ai = (item instanceof ArchiveInfo) ? (ArchiveInfo) item : null; + PackageInfo packageInfo = (item instanceof PackageInfo) ? (PackageInfo) item : null; boolean needUpdate = true; if (!mAcceptSameAllLicense && mLicenseRadioAcceptLicense.getSelection()) { // Accept all has been switched on. Mark all packages as accepted - List list = null; + List list = null; if (item instanceof LicenseEntry) { - list = ((LicenseEntry) item).getArchives(); - } else if (ai != null) { - Object p = ((NewArchivesContentProvider) mTreeViewPackage.getContentProvider()) - .getParent(ai); + list = ((LicenseEntry) item).getPackageInfoList(); + } else if (packageInfo != null) { + Object p = ((NewPackagesContentProvider) mTreeViewPackage.getContentProvider()) + .getParent(packageInfo); if (p instanceof LicenseEntry) { - list = ((LicenseEntry) p).getArchives(); + list = ((LicenseEntry) p).getPackageInfoList(); } } if (list != null && list.size() > 0) { mAcceptSameAllLicense = true; - for(ArchiveInfo ai2 : list) { - ai2.setAccepted(true); - ai2.setRejected(false); + for(PackageInfo packageInfo2 : list) { + packageInfo2.setAccepted(true); + packageInfo2.setRejected(false); + unacceptedLicenses.remove(packageInfo2.getNewPackage()); } } - } else if (ai != null && mLicenseRadioAccept.getSelection()) { + } else if (packageInfo != null && mLicenseRadioAccept.getSelection()) { // Accept only this one mAcceptSameAllLicense = false; - ai.setAccepted(true); - ai.setRejected(false); - - } else if (ai != null && mLicenseRadioReject.getSelection()) { + packageInfo.setAccepted(true); + packageInfo.setRejected(false); + unacceptedLicenses.remove(packageInfo.getNewPackage()); + } else if (packageInfo != null && mLicenseRadioReject.getSelection()) { // Reject only this one mAcceptSameAllLicense = false; - ai.setAccepted(false); - ai.setRejected(true); - + packageInfo.setAccepted(false); + packageInfo.setRejected(true); + unacceptedLicenses.add(packageInfo.getNewPackage()); } else { needUpdate = false; } @@ -803,13 +697,13 @@ private void onLicenseRadioSelected() { if (mAcceptSameAllLicense) { mTreeViewPackage.refresh(); } else { - mTreeViewPackage.refresh(ai); + mTreeViewPackage.refresh(packageInfo); mTreeViewPackage.refresh( - ((NewArchivesContentProvider) mTreeViewPackage.getContentProvider()). - getParent(ai)); + ((NewPackagesContentProvider) mTreeViewPackage.getContentProvider()). + getParent(packageInfo)); } - displayMissingDependency(ai); - updateLicenceRadios(ai); + displayMissingDependency(packageInfo); + updateLicenceRadios(packageInfo); } } @@ -819,45 +713,129 @@ private void onLicenseRadioSelected() { private void onPackageDoubleClick() { Object item = getSelectedItem(); - if (item instanceof ArchiveInfo) { - ArchiveInfo ai = (ArchiveInfo) item; - boolean wasAccepted = ai.isAccepted(); - ai.setAccepted(!wasAccepted); - ai.setRejected(wasAccepted); + if (item instanceof PackageInfo) { + PackageInfo packageInfo = (PackageInfo) item; + boolean wasAccepted = packageInfo.isAccepted(); + packageInfo.setAccepted(!wasAccepted); + packageInfo.setRejected(wasAccepted); // update state mAcceptSameAllLicense = false; - mTreeViewPackage.refresh(ai); + mTreeViewPackage.refresh(packageInfo); // refresh parent since its icon might have changed. mTreeViewPackage.refresh( - ((NewArchivesContentProvider) mTreeViewPackage.getContentProvider()). - getParent(ai)); + ((NewPackagesContentProvider) mTreeViewPackage.getContentProvider()). + getParent(packageInfo)); - displayMissingDependency(ai); - updateLicenceRadios(ai); + displayMissingDependency(packageInfo); + updateLicenceRadios(packageInfo); } else if (item instanceof LicenseEntry) { mTreeViewPackage.setExpandedState(item, !mTreeViewPackage.getExpandedState(item)); } } + /** + * Computes and displays missing dependencies. + * + * If there's a selected package, check the dependency for that one. + * Otherwise display the first missing dependency of any other package. + */ + private void displayMissingDependency(PackageInfo packageInfo) { + String error = null; + + try { + if (packageInfo != null) { + if (packageInfo.isAccepted()) { + // Case where this package is accepted but blocked by another non-accepted one + List required = InstallerUtil.computeRequiredPackages( + Collections.singletonList(packageInfo.getNewPackage()), mSdkContext.getPackages(), + mSdkContext.getProgressIndicator()); + if ((required != null && required.size() > 0)) { + for (RemotePackage dependency : required) { + if (unacceptedLicenses.contains(dependency)) { + error = String.format("This package depends on '%1$s'.", + dependency.getDisplayName()); + return; + } + } + } + } else { + /* + // Case where this package blocks another one when not accepted + for (PackageInfo adep : packageInfo.getDependenciesFor()) { + // It only matters if the blocked one is accepted + if (adep.isAccepted()) { + error = String.format("Package '%1$s' depends on this one.", + adep.getShortDescription()); + return; + } + } + */ + } + } +/* + // If there is no missing dependency on the current selection, + // just find the first missing dependency of any other package. + for (PackageInfo packageInfo2 : mArchives) { + if (packageInfo2 == packageInfo) { + // We already processed that one above. + continue; + } + if (packageInfo2.isAccepted()) { + // The user requested to install this package. + // Check if all its dependencies are met. + PackageInfo[] adeps = packageInfo2.getDependsOn(); + if (adeps != null) { + for (PackageInfo adep : adeps) { + if (!adep.isAccepted()) { + error = String.format("Package '%1$s' depends on '%2$s'", + packageInfo2.getShortDescription(), + adep.getShortDescription()); + return; + } + } + } + } else { + // The user did not request to install this package. + // Check whether this package blocks another one when not accepted. + for (PackageInfo adep : packageInfo2.getDependenciesFor()) { + // It only matters if the blocked one is accepted + // or if it's a local archive that is already installed (these + // are marked as implicitly accepted, so it's the same test.) + if (adep.isAccepted()) { + error = String.format("Package '%1$s' depends on '%2$s'", + adep.getShortDescription(), + packageInfo2.getShortDescription()); + return; + } + } + } + } +*/ + } finally { + mErrorLabel.setText(error == null ? "" : error); //$NON-NLS-1$ + } + } + + /** * Provides the labels for the tree view. * Root branches are {@link LicenseEntry} elements. - * Leave nodes are {@link ArchiveInfo} which all have the same license. + * Leave nodes are {@link PackageInfo} which all have the same license. */ - private class NewArchivesLabelProvider extends LabelProvider { + private class NewPackagesLabelProvider extends LabelProvider { @Override public Image getImage(Object element) { - if (element instanceof ArchiveInfo) { - // Archive icon: accepted (green), rejected (red), not set yet (question mark) - ArchiveInfo ai = (ArchiveInfo) element; + if (element instanceof PackageInfo) { + // Package icon: accepted (green), rejected (red), not set yet (question mark) + PackageInfo packageInfo = (PackageInfo) element; - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { - if (ai.isAccepted()) { + if (packageInfo.isAccepted()) { return imgFactory.getImageByName("accept_icon16.png"); - } else if (ai.isRejected()) { + } else if (packageInfo.isRejected()) { return imgFactory.getImageByName("reject_icon16.png"); } return imgFactory.getImageByName("unknown_icon16.png"); @@ -867,13 +845,13 @@ public Image getImage(Object element) { } else if (element instanceof LicenseEntry) { // License icon: green if all below are accepted, red if all rejected, otherwise // no icon. - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { boolean allAccepted = true; boolean allRejected = true; - for (ArchiveInfo ai : ((LicenseEntry) element).getArchives()) { - allAccepted = allAccepted && ai.isAccepted(); - allRejected = allRejected && ai.isRejected(); + for (PackageInfo packageInfo : ((LicenseEntry) element).getPackageInfoList()) { + allAccepted = allAccepted && packageInfo.isAccepted(); + allRejected = allRejected && packageInfo.isRejected(); } if (allAccepted && !allRejected) { return imgFactory.getImageByName("accept_icon16.png"); @@ -882,7 +860,6 @@ public Image getImage(Object element) { } } } - return null; } @@ -891,20 +868,17 @@ public String getText(Object element) { if (element instanceof LicenseEntry) { return ((LicenseEntry) element).getLicenseRef(); - } else if (element instanceof ArchiveInfo) { - ArchiveInfo ai = (ArchiveInfo) element; + } else if (element instanceof PackageInfo) { + PackageInfo packageInfo = (PackageInfo) element; - String desc = ai.getShortDescription(); - - if (ai.isDependencyFor()) { - desc += " [*]"; - } + String desc = packageInfo.getNewPackage().getDisplayName(); + // if (packageInfo.isDependencyFor()) { + // desc += " [*]"; + // } return desc; - } - - assert element instanceof String || element instanceof ArchiveInfo; + assert element instanceof String || element instanceof PackageInfo; return null; } } @@ -912,9 +886,9 @@ public String getText(Object element) { /** * Provides the content for the tree view. * Root branches are {@link LicenseEntry} elements. - * Leave nodes are {@link ArchiveInfo} which all have the same license. + * Leave nodes are {@link PackageInfo} which all have the same license. */ - private class NewArchivesContentProvider implements ITreeContentProvider { + private class NewPackagesContentProvider implements ITreeContentProvider { private List mInput; @Override @@ -942,7 +916,7 @@ public boolean hasChildren(Object parent) { return true; } else if (parent instanceof LicenseEntry) { - return ((LicenseEntry) parent).getArchives().size() > 0; + return ((LicenseEntry) parent).getPackageInfoList().size() > 0; } return false; @@ -959,7 +933,7 @@ public Object[] getChildren(Object parent) { return ((List) parent).toArray(); } else if (parent instanceof LicenseEntry) { - return ((LicenseEntry) parent).getArchives().toArray(); + return ((LicenseEntry) parent).getPackageInfoList().toArray(); } return new Object[0]; @@ -970,9 +944,9 @@ public Object getParent(Object child) { if (child instanceof LicenseEntry) { return ((LicenseEntry) child).getRoot(); - } else if (child instanceof ArchiveInfo && mInput != null) { + } else if (child instanceof PackageInfo && mInput != null) { for (LicenseEntry entry : mInput) { - if (entry.getArchives().contains(child)) { + if (entry.getPackageInfoList().contains(child)) { return entry; } } @@ -989,15 +963,15 @@ public Object getParent(Object child) { private static class LicenseEntry { private final List mRoot; private final String mLicenseRef; - private final List mArchives; + private final List mPackageInfoList; public LicenseEntry( @NonNull List root, @NonNull String licenseRef, - @NonNull List archives) { + @NonNull List packageInfoList) { mRoot = root; mLicenseRef = licenseRef; - mArchives = archives; + mPackageInfoList = packageInfoList; } @NonNull @@ -1011,8 +985,8 @@ public String getLicenseRef() { } @NonNull - public List getArchives() { - return mArchives; + public List getPackageInfoList() { + return mPackageInfoList; } } @@ -1023,10 +997,10 @@ public List getArchives() { * Elements with no license are left at the root. * * @param archives The non-null collection of archive info to display. Ideally non-empty. - * @return A list of {@link LicenseEntry}, each containing a list of {@link ArchiveInfo}. + * @return A list of {@link LicenseEntry}, each containing a list of {@link PackageInfo}. */ @NonNull - private List createTreeInput(@NonNull Collection archives) { + private List createTreeInput(@NonNull List packageInfoList) { // Build an ordered map with all the licenses, ordered by license ref name. final String noLicense = "No license"; //NLS @@ -1046,51 +1020,43 @@ public int compare(String s1, String s2) { } }; - Map> map = new TreeMap>(comp); + Map> packageInfoMap = new TreeMap>(comp); - for (ArchiveInfo info : archives) { + for (PackageInfo info : packageInfoList) { String ref = noLicense; - License license = getLicense(info); - if (license != null && license.getLicenseRef() != null) { - ref = prettyLicenseRef(license.getLicenseRef()); + License license = info.getNewPackage().getLicense(); + if (license != null) { + ref = license.getId(); //prettyLicenseRef(license.getLicenseRef()); } - List list = map.get(ref); + List list = packageInfoMap.get(ref); if (list == null) { - map.put(ref, list = new ArrayList()); + packageInfoMap.put(ref, list = new ArrayList()); } list.add(info); } // Transform result into a list List licensesList = new ArrayList(); - for (Map.Entry> entry : map.entrySet()) { + for (Map.Entry> entry : packageInfoMap.entrySet()) { licensesList.add(new LicenseEntry(licensesList, entry.getKey(), entry.getValue())); } - return licensesList; } - /** - * Helper method to retrieve the {@link License} for a given {@link ArchiveInfo}. - * - * @param ai The archive info. Can be null. - * @return The license for the package owning the archive. Can be null. - */ - @Nullable - private License getLicense(@Nullable ArchiveInfo ai) { - if (ai != null) { - Archive aNew = ai.getNewArchive(); - if (aNew != null) { - Package pNew = aNew.getParentPackage(); - if (pNew != null) { - return pNew.getLicense(); - } - } + private void init(List newPackages) { + Iterator iterator = newPackages.iterator(); + while(iterator.hasNext()) + mPackages.add(new PackageInfo(iterator.next())); + } + + private void init(Collection updates) { + Iterator iterator = updates.iterator(); + while(iterator.hasNext()) { + UpdatablePackage updatable = iterator.next(); + mPackages.add(new PackageInfo(updatable.getRemote(), updatable.getLocal())); } - return null; - } - + } /** * Reformats the licenseRef to be more human-readable. * It's an XML ref and in practice it looks like [oem-]android-[type]-license. diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java index 99c5eb22..65d71937 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java @@ -18,27 +18,23 @@ import com.android.SdkConstants; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.sources.SdkSourceProperties; -import com.android.sdklib.internal.repository.updater.SettingsController; -import com.android.sdklib.internal.repository.updater.SettingsController.Settings; -import com.android.sdklib.repository.ISdkChangeListener; import com.android.sdkuilib.internal.repository.AboutDialog; import com.android.sdkuilib.internal.repository.ISdkUpdaterWindow; import com.android.sdkuilib.internal.repository.MenuBarWrapper; +import com.android.sdkuilib.internal.repository.Settings; import com.android.sdkuilib.internal.repository.SettingsDialog; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; +import org.eclipse.andmore.base.resources.ImageFactory; import com.android.sdkuilib.internal.repository.ui.PackagesPage.MenuAction; -import com.android.sdkuilib.internal.tasks.ILogUiProvider; -import com.android.sdkuilib.internal.tasks.ProgressView; -import com.android.sdkuilib.internal.tasks.ProgressViewFactory; import com.android.sdkuilib.internal.widgets.ImgDisabledButton; import com.android.sdkuilib.internal.widgets.ToggleButton; import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; +import com.android.sdkuilib.repository.ISdkChangeListener; import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; import com.android.utils.ILogger; +import java.util.Iterator; + +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -71,8 +67,7 @@ public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow { private final Shell mParentShell; private final SdkInvocationContext mContext; - /** Internal data shared between the window and its pages. */ - private final SwtUpdaterData mSwtUpdaterData; + private final SdkContext mSdkContext; // --- UI members --- @@ -82,7 +77,6 @@ public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow { private Label mStatusText; private ImgDisabledButton mButtonStop; private ToggleButton mButtonShowLog; - private SettingsController mSettingsController; private LogWindow mLogWindow; /** @@ -90,38 +84,17 @@ public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow { * * @param parentShell Parent shell. * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. + * @param sdkContext SDK handler and repo manager * @param context The {@link SdkInvocationContext} to change the behavior depending on who's * opening the SDK Manager. */ public SdkUpdaterWindowImpl2( Shell parentShell, - ILogger sdkLog, - String osSdkRoot, + SdkContext sdkContext, SdkInvocationContext context) { mParentShell = parentShell; mContext = context; - mSwtUpdaterData = new SwtUpdaterData(osSdkRoot, sdkLog); - } - - /** - * Creates a new window. Caller must call open(), which will block. - *

- * This is to be used when the window is opened from {@link AvdManagerWindowImpl1} - * to share the same {@link SwtUpdaterData} structure. - * - * @param parentShell Parent shell. - * @param swtUpdaterData The parent's updater data. - * @param context The {@link SdkInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public SdkUpdaterWindowImpl2( - Shell parentShell, - SwtUpdaterData swtUpdaterData, - SdkInvocationContext context) { - mParentShell = parentShell; - mContext = context; - mSwtUpdaterData = swtUpdaterData; + mSdkContext = sdkContext; } /** @@ -150,10 +123,6 @@ public void open() { } } } - - SdkSourceProperties p = new SdkSourceProperties(); - p.save(); - dispose(); //$hide$ } @@ -189,7 +158,7 @@ public void widgetDisposed(DisposeEvent e) { } private void createContents() { - mPkgPage = new PackagesPage(mShell, SWT.NONE, mSwtUpdaterData, mContext); + mPkgPage = new PackagesPage(mShell, SWT.NONE, mSdkContext, mContext); mPkgPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); Composite composite1 = new Composite(mShell, SWT.NONE); @@ -231,7 +200,6 @@ public void handleEvent(Event event) { }); } - @SuppressWarnings("unused") // MenuItem works using side effects private void createMenuBar() { Menu menuBar = new Menu(mShell, SWT.BAR); @@ -242,20 +210,19 @@ private void createMenuBar() { Menu menuPkgs = new Menu(menuBarPackages); menuBarPackages.setMenu(menuPkgs); - MenuItem showUpdatesNew = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle()); + MenuAction.TOGGLE_SHOW_NEW_PKG.getMenuStyle()); showUpdatesNew.setText( - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle()); + MenuAction.TOGGLE_SHOW_NEW_PKG.getMenuTitle()); mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew); + MenuAction.TOGGLE_SHOW_NEW_PKG, showUpdatesNew); - MenuItem showInstalled = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle()); - showInstalled.setText( - MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled); + //MenuItem showInstalled = new MenuItem(menuPkgs, + // MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle()); + //showInstalled.setText( + // MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle()); + //mPkgPage.registerMenuAction( + // MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled); MenuItem showObsoletePackages = new MenuItem(menuPkgs, MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle()); @@ -264,13 +231,6 @@ private void createMenuBar() { mPkgPage.registerMenuAction( MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages); - MenuItem showArchives = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle()); - showArchives.setText( - MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives); - new MenuItem(menuPkgs, SWT.SEPARATOR); MenuItem reload = new MenuItem(menuPkgs, @@ -279,7 +239,6 @@ private void createMenuBar() { MenuAction.RELOAD.getMenuTitle()); mPkgPage.registerMenuAction( MenuAction.RELOAD, reload); - MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE); menuBarTools.setText("Tools"); @@ -296,14 +255,6 @@ public void widgetSelected(SelectionEvent event) { } }); } - - MenuItem manageSources = new MenuItem(menuTools, - MenuAction.SHOW_ADDON_SITES.getMenuStyle()); - manageSources.setText( - MenuAction.SHOW_ADDON_SITES.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.SHOW_ADDON_SITES, manageSources); - if (mContext == SdkInvocationContext.STANDALONE || mContext == SdkInvocationContext.IDE) { try { new MenuBarWrapper(APP_NAME, menuTools) { @@ -311,14 +262,14 @@ public void widgetSelected(SelectionEvent event) { public void onPreferencesMenuSelected() { // capture a copy of the initial settings - Settings settings1 = new Settings(mSettingsController.getSettings()); + Settings settings1 = mSdkContext.getSettings().copy(); // open the dialog and wait for it to close - SettingsDialog sd = new SettingsDialog(mShell, mSwtUpdaterData); + SettingsDialog sd = new SettingsDialog(mShell, mSdkContext); sd.open(); // get the new settings - Settings settings2 = mSettingsController.getSettings(); + Settings settings2 = mSdkContext.getSettings(); // We need to reload the package list if the http mode or the preview // modes have changed. @@ -330,27 +281,27 @@ public void onPreferencesMenuSelected() { @Override public void onAboutMenuSelected() { - AboutDialog ad = new AboutDialog(mShell, mSwtUpdaterData); + AboutDialog ad = new AboutDialog(mShell, mSdkContext); ad.open(); } @Override public void printError(String format, Object... args) { - if (mSwtUpdaterData != null) { - mSwtUpdaterData.getSdkLog().error(null, format, args); + if (mSdkContext != null) { + mSdkContext.getSdkLog().error(null, format, args); } } }; } catch (Throwable e) { - mSwtUpdaterData.getSdkLog().error(e, "Failed to setup menu bar"); + mSdkContext.getSdkLog().error(e, "Failed to setup menu bar"); e.printStackTrace(); } } } private Image getImage(String filename) { - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { return imgFactory.getImageByName(filename); } @@ -367,7 +318,7 @@ private Image getImage(String filename) { */ private void createLogWindow() { mLogWindow = new LogWindow(mShell, - mContext == SdkInvocationContext.IDE ? mSwtUpdaterData.getSdkLog() : null); + mContext == SdkInvocationContext.IDE ? mSdkContext.getSdkLog() : null); mLogWindow.open(); } @@ -383,7 +334,7 @@ private void createLogWindow() { */ @Override public void addListener(ISdkChangeListener listener) { - mSwtUpdaterData.addListeners(listener); + mSdkContext.getSdkHelper().addListeners(listener); } /** @@ -392,7 +343,7 @@ public void addListener(ISdkChangeListener listener) { */ @Override public void removeListener(ISdkChangeListener listener) { - mSwtUpdaterData.removeListener(listener); + mSdkContext.getSdkHelper().removeListener(listener); } // --- Internals & UI Callbacks ----------- @@ -401,9 +352,7 @@ public void removeListener(ISdkChangeListener listener) { * Called before the UI is created. */ private void preCreateContent() { - mSwtUpdaterData.setWindowShell(mShell); - // We need the UI factory to create the UI - mSwtUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay())); + mSdkContext.getSdkHelper().setWindowShell(mShell); // Note: we can't create the TaskFactory yet because we need the UI // to be created first, so this is done in postCreateContent(). } @@ -415,12 +364,11 @@ private void preCreateContent() { * Returns true if we should show the window. */ private boolean postCreateContent() { - ProgressViewFactory factory = new ProgressViewFactory(); // This class delegates all logging to the mLogWindow window // and filters errors to make sure the window is visible when // an error is logged. - ILogUiProvider logAdapter = new ILogUiProvider() { + SdkProgressFactory.ISdkLogWindow logAdapter = new SdkProgressFactory.ISdkLogWindow() { @Override public void setDescription(String description) { mLogWindow.setDescription(description); @@ -439,7 +387,10 @@ public void logVerbose(String log) { @Override public void logError(String log) { mLogWindow.logError(log); - + } + @Override + public void show() + { // Run the window visibility check/toggle on the UI thread. // Note: at least on Windows, it seems ok to check for the window visibility // on a sub-thread but that doesn't seem cross-platform safe. We shouldn't @@ -460,25 +411,26 @@ public void run() { } } }; - - factory.setProgressView( - new ProgressView(mStatusText, mProgressBar, mButtonStop, logAdapter)); - mSwtUpdaterData.setTaskFactory(factory); - + SdkProgressFactory factory = new SdkProgressFactory(mStatusText, mProgressBar, mButtonStop, logAdapter); setWindowImage(mShell); - - setupSources(); - initializeSettings(); - - if (mSwtUpdaterData.checkIfInitFailed()) { + if (!initializeSettings()) return false; + if (mSdkContext.hasError()) + { + ILogger logger = (ILogger)factory; + Iterator iterator = mSdkContext.getLogMessages().iterator(); + while(iterator.hasNext()) + logger.error(null, iterator.next()); + return false; + } + mSdkContext.setSdkLogger(factory); + mSdkContext.setSdkProgressIndicator(factory); + // TODO - Consider how to signal SDK loaded + //mSdkContext.getSdkHelper().broadcastOnSdkLoaded(mSdkContext.getSdkLog()); - mSwtUpdaterData.broadcastOnSdkLoaded(); - - // Tell the one page its the selected one - mPkgPage.performFirstLoad(); - + // Display packages + mPkgPage.onReady(factory, factory.getProgressControl(), factory); return true; } @@ -493,8 +445,8 @@ private void setWindowImage(Shell shell) { imageName = "android_icon_128.png"; //$NON-NLS-1$ } - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { shell.setImage(imgFactory.getImageByName(imageName)); } @@ -506,38 +458,34 @@ private void setWindowImage(Shell shell) { */ private void dispose() { mLogWindow.close(); - mSwtUpdaterData.getSources().saveUserAddons(mSwtUpdaterData.getSdkLog()); } /** * Callback called when the window shell is disposed. */ private void onAndroidSdkUpdaterDispose() { - if (mSwtUpdaterData != null) { - ImageFactory imgFactory = mSwtUpdaterData.getImageFactory(); + if (mSdkContext != null) { + ImageFactory imgFactory = mSdkContext.getSdkHelper().getImageFactory(); if (imgFactory != null) { imgFactory.dispose(); } } } - /** - * Used to initialize the sources. - */ - private void setupSources() { - mSwtUpdaterData.setupDefaultSources(); - } - /** * Initializes settings. * This must be called after addExtraPages(), which created a settings page. * Iterate through all the pages to find the first (and supposedly unique) setting page, * and use it to load and apply these settings. */ - private void initializeSettings() { - mSettingsController = mSwtUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); + private boolean initializeSettings() { + Settings settings = new Settings(); + if (settings.initialize(mSdkContext.getSdkLog())) + { + mSdkContext.setSettings(settings); + return true; + } + return false; } private void onToggleLogWindow() { @@ -549,24 +497,20 @@ private void onToggleLogWindow() { } private void onStopSelected() { - // TODO + mSdkContext.getProgressIndicator().cancel(); } private void onAvdManager() { - ITaskFactory oldFactory = mSwtUpdaterData.getTaskFactory(); - try { AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1( mShell, - mSwtUpdaterData, + mSdkContext, AvdInvocationContext.DIALOG); win.open(); } catch (Exception e) { - mSwtUpdaterData.getSdkLog().error(e, "AVD Manager window error"); - } finally { - mSwtUpdaterData.setTaskFactory(oldFactory); - } + mSdkContext.getSdkLog().error(e, "AVD Manager window error"); + } } // End of hiding from SWT Designer diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java index e10a0c24..23d4a416 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java @@ -16,8 +16,8 @@ package com.android.sdkuilib.internal.tasks; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.UserCredentials; import org.eclipse.swt.widgets.ProgressBar; @@ -73,6 +73,17 @@ interface IProgressUiProvider extends ILogUiProvider { */ public abstract boolean displayPrompt(String title, String message); + /** + * Display info dialog box. + * + * This implementation allow this to be called from any thread, it + * makes sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + */ + public abstract void displayInfo(String title, String message); + /** * Launch an interface which asks for login credentials. Implementations * MUST allow this to be called from any thread, e.g. by making sure the diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTask.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTask.java index 2563a5ff..00f6c6fa 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTask.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTask.java @@ -16,8 +16,8 @@ package com.android.sdkuilib.internal.tasks; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskMonitor; import org.eclipse.swt.widgets.Shell; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java index 1a16799f..5b4b1048 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java @@ -17,8 +17,8 @@ package com.android.sdkuilib.internal.tasks; import com.android.SdkConstants; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.UserCredentials; import com.android.sdkuilib.ui.AuthenticationDialog; import com.android.sdkuilib.ui.GridDialog; import com.android.utils.Pair; @@ -414,6 +414,28 @@ public void run() { return result[0]; } + + /** + * Display info dialog box. + * + * This implementation allow this to be called from any thread, it + * makes sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + */ + @Override + public void displayInfo(String title, String message) { + Display display = mDialogShell.getDisplay(); + + display.syncExec(new Runnable() { + @Override + public void run() { + MessageDialog.openInformation(mDialogShell, title, message); + } + }); + } + /** * This method opens a pop-up window which requests for User Login and * password. diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java index bd2cc14f..da4e94d5 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java @@ -16,9 +16,9 @@ package com.android.sdkuilib.internal.tasks; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskFactory; +import com.android.sdkuilib.internal.repository.ITaskMonitor; import org.eclipse.swt.widgets.Shell; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressView.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressView.java index fe7d6c51..f01164f5 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressView.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressView.java @@ -16,9 +16,9 @@ package com.android.sdkuilib.internal.tasks; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.UserCredentials; import com.android.sdkuilib.ui.AuthenticationDialog; import com.android.sdkuilib.ui.GridDialog; @@ -33,6 +33,10 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Widget; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.util.concurrent.atomic.AtomicReference; @@ -113,13 +117,19 @@ public void handleEvent(Event event) { public void startTask( final String title, final ITaskMonitor parentMonitor, - final ITask task) { + final ITask task, + boolean sync) { if (task != null) { try { if (parentMonitor == null && !mProgressBar.isDisposed()) { - mLabel.setText(title); - mProgressBar.setSelection(0); - mProgressBar.setEnabled(true); + syncExec(mProgressBar, new Runnable() { + @Override + public void run() { + mLabel.setText(title); + mProgressBar.setSelection(0); + mProgressBar.setEnabled(true); + } + }); changeState(ProgressView.State.ACTIVE); } @@ -167,29 +177,42 @@ public void run() { final Thread t = new Thread(r, title); t.start(); - - // Process the app's event loop whilst we wait for the thread to finish - while (!mProgressBar.isDisposed() && t.isAlive()) { - Display display = mProgressBar.getDisplay(); - if (!mProgressBar.isDisposed() && !display.readAndDispatch()) { - display.sleep(); - } - } + if (sync) + // Process the app's event loop whilst we wait for the thread to finish + while (!mProgressBar.isDisposed() && t.isAlive()) { + Display display = mProgressBar.getDisplay(); + if (!mProgressBar.isDisposed() && !display.readAndDispatch()) { + display.sleep(); + } + } } } catch (Exception e) { - // TODO log - + StringWriter builder = new StringWriter(); + builder.append(e.getMessage()).append("\n"); + PrintWriter writer = new PrintWriter(builder); + e.printStackTrace(writer); + mLog.logError(builder.toString()); } finally { - if (parentMonitor == null && !mProgressBar.isDisposed()) { - changeState(ProgressView.State.IDLE); - mProgressBar.setSelection(0); - mProgressBar.setEnabled(false); + if (parentMonitor == null && sync && !mProgressBar.isDisposed()) { + endTask(); } } } } - private void syncExec(final Widget widget, final Runnable runnable) { + public void endTask() + { + changeState(ProgressView.State.IDLE); + syncExec(mProgressBar, new Runnable() { + @Override + public void run() { + mProgressBar.setSelection(0); + mProgressBar.setEnabled(false); + } + }); + } + + public void syncExec(final Widget widget, final Runnable runnable) { if (widget != null && !widget.isDisposed()) { widget.getDisplay().syncExec(new Runnable() { @Override @@ -222,7 +245,10 @@ public void run() { @Override public boolean isCancelRequested() { - return mState != State.ACTIVE; + boolean cancelStatus = mState != State.ACTIVE; + if (cancelStatus) + log("Stop button pressed"); + return cancelStatus; } /** @@ -337,6 +363,27 @@ public void run() { return result[0]; } + /** + * Display info dialog box. + * + * This implementation allow this to be called from any thread, it + * makes sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + */ + @Override + public void displayInfo(String title, String message) { + + syncExec(mProgressBar, new Runnable() { + @Override + public void run() { + Shell shell = mProgressBar.getShell(); + MessageDialog.openInformation(shell, title, message); + } + }); + } + /** * This method opens a pop-up window which requests for User Credentials. * diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java deleted file mode 100644 index 1d39c597..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2009 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.sdkuilib.internal.tasks; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; - -/** - * An {@link ITaskFactory} that creates a new {@link ProgressTask} dialog - * for each new task. - */ -public final class ProgressViewFactory implements ITaskFactory { - - private ProgressView mProgressView; - - public ProgressViewFactory() { - } - - public void setProgressView(ProgressView progressView) { - mProgressView = progressView; - } - - @Override - public void start(String title, ITask task) { - start(title, null /*monitor*/, task); - } - - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - assert mProgressView != null; - mProgressView.startTask(title, parentMonitor, task); - } -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/SdkProgressIndicator.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/SdkProgressIndicator.java new file mode 100644 index 00000000..6d27d15a --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/SdkProgressIndicator.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2017 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.sdkuilib.internal.tasks; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import com.android.repository.api.ProgressIndicator; +import com.android.sdkuilib.internal.repository.ITaskMonitor; + +/** + * @author Andrew Bowley + * + * 12-11-2017 + */ +public class SdkProgressIndicator implements ProgressIndicator { + // Use Monitor max count value convert fractions to integer values + private static final int MAX_COUNT = 10000; + + private final ITaskMonitor monitor; + private volatile boolean isCancelled = false; + private volatile boolean cancellable = true; + // TODO - implement indeterminate cursor + private volatile boolean indeterminate = false; + + /** + * + */ + public SdkProgressIndicator(ITaskMonitor monitor) { + this.monitor = monitor; + monitor.setProgressMax(MAX_COUNT); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#cancel() + */ + @Override + public void cancel() { + if (cancellable) + // TODO - Consider informing user request denied or disable stop button when not cancellable + isCancelled = true; + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#getFraction() + */ + @Override + public double getFraction() { + return MAX_COUNT / monitor.getProgress(); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#isCanceled() + */ + @Override + public boolean isCanceled() { + return isCancelled || monitor.isCancelRequested(); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#isCancellable() + */ + @Override + public boolean isCancellable() { + return cancellable; + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#isIndeterminate() + */ + @Override + public boolean isIndeterminate() { + return indeterminate; + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#logError(java.lang.String) + */ + @Override + public void logError(String message) { + monitor.logError(message); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#logError(java.lang.String, java.lang.Throwable) + */ + @Override + public void logError(String message, Throwable throwable) { + monitor.error(throwable, message); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#logInfo(java.lang.String) + */ + @Override + public void logInfo(String message) { + monitor.info(message); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#logWarning(java.lang.String) + */ + @Override + public void logWarning(String message) { + monitor.warning(message); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#logWarning(java.lang.String, java.lang.Throwable) + */ + @Override + public void logWarning(String message, Throwable throwable) { + StringWriter builder = new StringWriter(); + builder.append(message); + if (throwable != null) { + builder.append("\n"); + PrintWriter writer = new PrintWriter(builder); + throwable.printStackTrace(writer); + } + monitor.warning(builder.toString()); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#setCancellable(boolean) + */ + @Override + public void setCancellable(boolean cancellable) { + this.cancellable = cancellable; + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#setFraction(double) + */ + @Override + public void setFraction(double fraction) { + int progress = fraction == 1.0 ? MAX_COUNT : (int)((double)MAX_COUNT * fraction); + monitor.incProgress(progress - monitor.getProgress()); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#setIndeterminate(boolean) + */ + @Override + public void setIndeterminate(boolean indeterminate) { + this.indeterminate = indeterminate; + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#setSecondaryText(java.lang.String) + */ + @Override + public void setSecondaryText(String text) { + // TODO - implement secondary text + monitor.logVerbose(text); + } + + /* (non-Javadoc) + * @see com.android.repository.api.ProgressIndicator#setText(java.lang.String) + */ + @Override + public void setText(String text) { + monitor.setDescription(text); + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java index eaeb7522..072a8629 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java @@ -17,8 +17,8 @@ package com.android.sdkuilib.internal.tasks; import com.android.annotations.NonNull; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.UserCredentials; /** * Internal class that implements the logic of an {@link ITaskMonitor}. @@ -177,6 +177,21 @@ public boolean displayPrompt(final String title, final String message) { return mUi.displayPrompt(title, message); } + /** + * Display info dialog box. + * + * Implementations MUST allow this to be called from any thread, e.g. by + * making sure the dialog is opened synchronously in the ui thread. + * + * @param title The title of the dialog box + * @param message The error message + */ + @Override + public void displayInfo(final String title, final String message) + { + mUi.displayInfo(title, message); + }; + /** * Displays a Login/Password dialog. This implementation allows this method to be * called from any thread, it makes sure the dialog is opened synchronously @@ -329,6 +344,11 @@ public boolean displayPrompt(String title, String message) { return mRoot.displayPrompt(title, message); } + @Override + public void displayInfo(String title, String message) { + mRoot.displayInfo(title, message); + } + @Override public UserCredentials displayLoginCredentialsPrompt(String title, String message) { return mRoot.displayLoginCredentialsPrompt(title, message); @@ -365,5 +385,6 @@ public void info(@NonNull String msgFormat, Object... arg) { public void verbose(@NonNull String msgFormat, Object... arg) { mRoot.verbose(msgFormat, arg); } + } } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java index 643732fb..4c633cc2 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java @@ -19,11 +19,11 @@ import com.android.annotations.NonNull; import com.android.sdklib.devices.Device; import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; import com.android.sdkuilib.internal.widgets.AvdCreationPresenter.IWidgetAdapter; -import com.android.utils.ILogger; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.widgets.Shell; /** @@ -42,11 +42,10 @@ public class AvdCreationDialog extends AvdCreationSwtView { public AvdCreationDialog(Shell shell, - AvdManager avdManager, - ImageFactory imageFactory, - ILogger log, - AvdInfo editAvdInfo) { - super(shell, imageFactory, new AvdCreationPresenter(avdManager, log, editAvdInfo)); + @NonNull SdkContext sdkContext, + @NonNull SdkTargets sdkTargets, + AvdAgent editAvdAgent) { + super(shell, sdkContext.getSdkHelper().getImageFactory(), new AvdCreationPresenter(sdkContext, sdkTargets, editAvdAgent)); } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationPresenter.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationPresenter.java index 338690f6..5926a03a 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationPresenter.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationPresenter.java @@ -20,11 +20,14 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.repository.Revision; +import com.android.repository.api.ProgressIndicator; import com.android.resources.Density; import com.android.resources.ScreenSize; +import com.android.sdklib.AndroidVersion; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISystemImage; -import com.android.sdklib.SystemImage; +import com.android.sdklib.SdkVersionInfo; import com.android.sdklib.devices.Camera; import com.android.sdklib.devices.CameraLocation; import com.android.sdklib.devices.Device; @@ -35,10 +38,15 @@ import com.android.sdklib.devices.Storage; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.avd.AvdManager.AvdConflict; import com.android.sdklib.internal.avd.HardwareProperties; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.local.LocalSdk; +import com.android.sdklib.repository.IdDisplay; +import com.android.sdklib.repository.meta.DetailsTypes; +import com.android.sdklib.repository.meta.DetailsTypes.AddonDetailsType.Libraries; +import com.android.sdklib.repository.meta.Library; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; +import com.android.sdkuilib.widgets.MessageBoxLog; import com.android.utils.ILogger; import com.android.utils.Pair; import com.google.common.base.Joiner; @@ -56,9 +64,10 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.andmore.sdktool.SdkContext; + /** * Implements all the logic of the {@link AvdCreationDialog}. *

@@ -71,12 +80,23 @@ * constructor. */ class AvdCreationPresenter { - + public enum AvdConflict + { + NO_CONFLICT, CONFLICT_EXISTING_AVD, CONFLICT_INVALID_AVD, CONFLICT_EXISTING_PATH; + + private AvdConflict() {} + } + public static final Pattern RE_AVD_NAME = Pattern.compile("[a-zA-Z0-9._-]+"); + public static final String CHARS_AVD_NAME = "a-z A-Z 0-9 . _ -"; + @NonNull private IWidgetAdapter mWidgets; private AvdManager mAvdManager; private ILogger mSdkLog; private AvdInfo mAvdInfo; + private AvdAgent mAvdAgent; + private final SdkContext mSdkContext; + private final SdkTargets mSdkTargets; private final TreeMap mCurrentTargets = new TreeMap(); @@ -86,8 +106,8 @@ class AvdCreationPresenter { private static final AvdSkinChoice SKIN_NONE = new AvdSkinChoice(SkinType.NONE, "No skin"); - private final List mComboDevices = new ArrayList(); - private final List mComboSkins = new ArrayList(); + private final List mComboDevices = new ArrayList<>(); + private final List mComboSkins = new ArrayList<>(); private final List mComboSystemImages = new ArrayList(); private final List mComboTargets = new ArrayList(); @@ -155,12 +175,16 @@ public interface IWidgetAdapter { } - public AvdCreationPresenter(@NonNull AvdManager avdManager, - @NonNull ILogger log, - @Nullable AvdInfo editAvdInfo) { - mAvdManager = avdManager; - mSdkLog = log; - mAvdInfo = editAvdInfo; + public AvdCreationPresenter(@NonNull SdkContext sdkContext, + @NonNull SdkTargets sdkTargets, + @Nullable AvdAgent editAvdAgent) { + mSdkContext = sdkContext; + mSdkTargets = sdkTargets; + mAvdManager = sdkContext.getAvdManager(); + mSdkLog = mSdkContext.getSdkLog(); + mAvdAgent = editAvdAgent; + if (editAvdAgent != null) + mAvdInfo = editAvdAgent.getAvd(); } /** Returns the AVD Created, if successful. */ @@ -204,7 +228,7 @@ public void onViewInit() { if (mAvdInfo != null) { - fillExistingAvdInfo(mAvdInfo); + fillExistingAvdInfo(mAvdAgent); } else if (mInitWithDevice != null) { fillInitialDeviceInfo(mInitWithDevice); } @@ -217,47 +241,22 @@ public void onViewInit() { private void initializeDevices() { - LocalSdk localSdk = mAvdManager.getLocalSdk(); - File location = localSdk.getLocation(); - if (location != null) { - DeviceManager deviceManager = DeviceManager.createInstance(location, mSdkLog); - Collection deviceList = deviceManager.getDevices(DeviceManager.ALL_DEVICES); - - // Sort - List nexus = new ArrayList(deviceList.size()); - List other = new ArrayList(deviceList.size()); - for (Device device : deviceList) { - if (isNexus(device) && !isGeneric(device)) { - nexus.add(device); - } else { - other.add(device); - } - } - Collections.reverse(other); - Collections.sort(nexus, new Comparator() { - @Override - public int compare(Device device1, Device device2) { - // Descending order of age - return nexusRank(device2) - nexusRank(device1); - } - }); - - mComboDevices.clear(); - mComboDevices.addAll(nexus); - mComboDevices.addAll(other); - - String[] labels = new String[mComboDevices.size()]; - for (int i = 0, n = mComboDevices.size(); i < n; i++) { - Device device = mComboDevices.get(i); - if (isNexus(device) && !isGeneric(device)) { - labels[i] = getNexusLabel(device); - } else { - labels[i] = getGenericLabel(device); - } - } + DeviceManager deviceManager = mSdkContext.getDeviceManager(); + List deviceList = new ArrayList<>(deviceManager.getDevices(DeviceManager.ALL_DEVICES)); + + // Sort + Collections.sort(deviceList, Device.getDisplayComparator()); - mWidgets.setComboItems(Ctrl.COMBO_DEVICE, labels); + mComboDevices.clear(); + mComboDevices.addAll(deviceList); + + String[] labels = new String[mComboDevices.size()]; + for (int i = 0, n = mComboDevices.size(); i < n; i++) { + Device device = mComboDevices.get(i); + labels[i] = getGenericLabel(device); } + + mWidgets.setComboItems(Ctrl.COMBO_DEVICE, labels); } @Nullable @@ -309,8 +308,8 @@ void onAvdNameModified() { // Case where we're creating a new AVD or editing an existing one // and the AVD name has been changed... check for name uniqueness. - Pair conflict = mAvdManager.isAvdNameConflicting(name); - if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) { + Pair conflict = isAvdNameConflicting(name); + if (conflict.getFirst() != AvdConflict.NO_CONFLICT) { // If we're changing the state from disabled to enabled, make sure // to uncheck the button, to force the user to voluntarily re-enforce it. // This happens when editing an existing AVD and changing the name from @@ -362,6 +361,26 @@ private void fillDeviceProperties(Device device) { break; case NODPI: break; + case ANYDPI: + break; + case DPI_260: + break; + case DPI_280: + break; + case DPI_300: + break; + case DPI_340: + break; + case DPI_360: + break; + case DPI_400: + break; + case DPI_420: + break; + case DPI_560: + break; + default: + break; } } else { switch (density) { @@ -380,6 +399,26 @@ private void fillDeviceProperties(Device device) { break; case NODPI: break; + case ANYDPI: + break; + case DPI_260: + break; + case DPI_280: + break; + case DPI_300: + break; + case DPI_340: + break; + case DPI_360: + break; + case DPI_400: + break; + case DPI_420: + break; + case DPI_560: + break; + default: + break; } } mWidgets.setText(Ctrl.TEXT_VM_HEAP, Integer.toString(vmHeapSize)); @@ -462,30 +501,31 @@ private void preloadTargetCombo() { index = -1; mComboTargets.clear(); - LocalSdk localSdk = mAvdManager.getLocalSdk(); - if (localSdk != null) { - for (IAndroidTarget target : localSdk.getTargets()) { - String name; - if (target.isPlatform()) { - name = String.format("%s - API Level %s", - target.getName(), - target.getVersion().getApiString()); - } else { - name = String.format("%s (%s) - API Level %s", - target.getName(), - target.getVendor(), - target.getVersion().getApiString()); - } - mCurrentTargets.put(name, target); - mWidgets.addComboItem(Ctrl.COMBO_TARGET, name); - mComboTargets.add(target); - if (!found) { - index++; - found = name.equals(selected); - } + for (IAndroidTarget target : mSdkTargets.getTargets()) { + String name; + if (target.isPlatform()) { + name = target.getFullName(); + } else { + name = target.getName(); + if (!name.equals(target.getVendor())) { + name = String.format("%s (%s) - API Level %s", + name, + target.getVendor(), + target.getVersion().getApiString()); + } else { + name = String.format("%s - API Level %s", + name, + target.getVersion().getApiString()); + } + } + mCurrentTargets.put(name, target); + mWidgets.addComboItem(Ctrl.COMBO_TARGET, name); + mComboTargets.add(target); + if (!found) { + index++; + found = name.equals(selected); } } - mWidgets.setEnabled(Ctrl.COMBO_TARGET, mCurrentTargets.size() > 0); if (found) { @@ -524,8 +564,7 @@ void reloadTagAbiCombo() { String targetName = mWidgets.getComboItem(Ctrl.COMBO_TARGET, index); IAndroidTarget target = mCurrentTargets.get(targetName); - ISystemImage[] systemImages = getSystemImages(target); - + Collection systemImages = getSystemImages(target); // If user explicitly selected an ABI before, preserve that option // If user did not explicitly select before (only one option before) // force them to select @@ -548,15 +587,16 @@ void reloadTagAbiCombo() { mWidgets.setComboItems(Ctrl.COMBO_TAG_ABI, null); mComboSystemImages.clear(); - int i; + int i = 0; boolean found = false; - for (i = 0; i < systemImages.length; i++) { - ISystemImage systemImage = systemImages[i]; + Iterator iterator = systemImages.iterator(); + while(iterator.hasNext()) { + SystemImage systemImage = iterator.next(); if (deviceTagId != null && !deviceTagId.equals(systemImage.getTag().getId())) { continue; } - mComboSystemImages.add(systemImage); String prettyAbiType = AvdInfo.getPrettyAbiType(systemImage); + mComboSystemImages.add(systemImage); mWidgets.addComboItem(Ctrl.COMBO_TAG_ABI, prettyAbiType); if (!found) { found = prettyAbiType.equals(selected); @@ -564,6 +604,7 @@ void reloadTagAbiCombo() { mWidgets.selectComboIndex(Ctrl.COMBO_TAG_ABI, i); } } + ++i; } mWidgets.setEnabled(Ctrl.COMBO_TAG_ABI, !mComboSystemImages.isEmpty()); @@ -575,7 +616,6 @@ void reloadTagAbiCombo() { mWidgets.selectComboIndex(Ctrl.COMBO_TAG_ABI, 0); } } - reloadSkinCombo(); } @@ -599,7 +639,7 @@ void reloadSkinCombo() { } // path of sdk/system-images - String sdkSysImgPath = new File(mAvdManager.getLocalSdk().getLocation(), + String sdkSysImgPath = new File(mSdkContext.getLocation(), SdkConstants.FD_SYSTEM_IMAGES).getAbsolutePath(); for (File skin : target.getSkins()) { @@ -678,10 +718,10 @@ void validatePage() { return; } - if (!AvdManager.RE_AVD_NAME.matcher(avdName).matches()) { + if (!RE_AVD_NAME.matcher(avdName).matches()) { error = String.format( "AVD name '%1$s' contains invalid characters.\nAllowed characters are: %2$s", - avdName, AvdManager.CHARS_AVD_NAME); + avdName, CHARS_AVD_NAME); setPageValid(false, error, null); return; } @@ -713,8 +753,8 @@ void validatePage() { IAndroidTarget target = mCurrentTargets.get(targetName); if (target != null && !target.isPlatform()) { - ISystemImage[] sis = target.getSystemImages(); - if (sis != null && sis.length > 0) { + Collection sis = mSdkTargets.getSystemImages(target); + if (sis != null && sis.size() > 0) { // Note: if an addon has no system-images of its own, it depends on its parent // platform and it wouldn't have been loaded properly if the platform were // missing so we don't need to double-check that part here. @@ -724,7 +764,7 @@ void validatePage() { String abiType = tagAbi.getSecond(); if (abiType != null && !abiType.isEmpty() && - target.getParent().getSystemImage(tag, abiType) == null) { + getSystemImage(target.getParent(), tag, abiType) == null) { // We have a system-image requirement but there is no such system image // loaded in the parent platform. This AVD won't run properly. warnings.add( @@ -875,7 +915,16 @@ boolean createAvd() { } IdDisplay tag = tagAbi.getFirst(); String abiType = tagAbi.getSecond(); - + ISystemImage systemImage = null; + Collection sysImgs = mSdkContext.getHandler().getSystemImageManager(mSdkContext.getProgressIndicator()).getImages(); + for (SystemImage img : sysImgs) { + if (img.getAbiType().equals(abiType)) { + systemImage = img; + break; + } + } + if (systemImage == null) + return false; // get the SD card data from the UI. String sdName = null; if (mWidgets.isChecked(Ctrl.RADIO_SDCARD_SIZE)) { @@ -939,7 +988,8 @@ boolean createAvd() { File avdFolder = null; try { - avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName); + AvdInfo.getDefaultAvdFolder( + mAvdManager, avdName, mSdkContext.getHandler().getFileOp(), false); } catch (AndroidLocationException e) { return false; } @@ -985,16 +1035,30 @@ boolean createAvd() { hwProps.put(HardwareProperties.HW_SDCARD, HardwareProperties.BOOLEAN_YES); } + /* + @NonNull File avdFolder, + @NonNull String avdName, + @NonNull ISystemImage systemImage, + @Nullable File skinFolder, + @Nullable String skinName, + @Nullable String sdcard, + @Nullable Map hardwareConfig, + @Nullable Map bootProps, + boolean deviceHasPlayStore, + boolean createSnapshot, + boolean removePrevious, + boolean editExisting, + @NonNull ILogger log) { + */ AvdInfo avdInfo = mAvdManager.createAvd(avdFolder, avdName, - target, - tag, - abiType, + systemImage, skinFolder, skinName, sdName, hwProps, device.getBootProps(), + false, // deviceHasPlayStore mWidgets.isChecked(Ctrl.CHECK_SNAPSHOT), mWidgets.isChecked(Ctrl.CHECK_FORCE_CREATION), mAvdInfo != null, // edit existing @@ -1038,12 +1102,12 @@ private ISystemImage getSelectedSysImg() { return null; } - private void fillExistingAvdInfo(AvdInfo avd) { - mWidgets.setText(Ctrl.TEXT_AVD_NAME, avd.getName()); - selectDevice(avd.getDeviceManufacturer(), avd.getDeviceName()); + private void fillExistingAvdInfo(AvdAgent avdAgent) { + mWidgets.setText(Ctrl.TEXT_AVD_NAME, avdAgent.getAvd().getName()); + selectDevice(avdAgent.getDeviceMfctr(), avdAgent.getDeviceName()); toggleCameras(); - IAndroidTarget target = avd.getTarget(); + IAndroidTarget target = avdAgent.getTarget(); if (target != null && !mCurrentTargets.isEmpty()) { // Try to select the target in the target combo. @@ -1061,13 +1125,12 @@ private void fillExistingAvdInfo(AvdInfo avd) { } } } - - ISystemImage[] systemImages = getSystemImages(target); - if (target != null && systemImages.length > 0) { - mWidgets.setEnabled(Ctrl.COMBO_TAG_ABI, systemImages.length > 1); - String abiType = AvdInfo.getPrettyAbiType(avd.getTag(), avd.getAbiType()); - int n = mWidgets.getComboSize(Ctrl.COMBO_TAG_ABI); - for (int i = 0; i < n; i++) { + Collection systemImages = getSystemImages(target); + if (target != null && systemImages.size() > 0) { + mWidgets.setEnabled(Ctrl.COMBO_TAG_ABI, systemImages.size() > 1); + String abiType = mAvdAgent.getPrettyAbiType(); + int count = mWidgets.getComboSize(Ctrl.COMBO_TAG_ABI); + for (int i = 0; i < count; i++) { if (abiType.equals(mWidgets.getComboItem(Ctrl.COMBO_TAG_ABI, i))) { mWidgets.selectComboIndex(Ctrl.COMBO_TAG_ABI, i); reloadSkinCombo(); @@ -1076,7 +1139,7 @@ private void fillExistingAvdInfo(AvdInfo avd) { } } - Map props = avd.getProperties(); + Map props = avdAgent.getAvd().getProperties(); if (props != null) { String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); @@ -1130,15 +1193,15 @@ private void fillExistingAvdInfo(AvdInfo avd) { // the AVD .ini skin path is relative to the SDK folder *or* is a numeric size. String skinIniPath = props.get(AvdManager.AVD_INI_SKIN_PATH); if (skinIniPath != null) { - File skinFolder = new File(mAvdManager.getLocalSdk().getLocation(), skinIniPath); - - for (int i = 0; i < mComboSkins.size(); i++) { - if (mComboSkins.get(i).hasPath() && - skinFolder.equals(mComboSkins.get(i).getPath())) { - mWidgets.selectComboIndex(Ctrl.COMBO_SKIN, i); - defaultSkinType = null; - break; - } + File skinFolder = getAvdPath(skinIniPath); + if (skinFolder != null) + for (int i = 0; i < mComboSkins.size(); i++) { + if (mComboSkins.get(i).hasPath() && + skinFolder.equals(mComboSkins.get(i).getPath())) { + mWidgets.selectComboIndex(Ctrl.COMBO_SKIN, i); + defaultSkinType = null; + break; + } } } @@ -1203,19 +1266,22 @@ private void fillExistingAvdInfo(AvdInfo avd) { } } - @SuppressWarnings("deprecation") + private File getAvdPath(String subDirectory) + { + File file = null; + try { + file = new File(mAvdManager.getBaseAvdFolder(), subDirectory); + } catch (AndroidLocationException e) { + mSdkContext.getSdkLog().error(e, subDirectory); + } + return file; + } + + private void fillInitialDeviceInfo(Device device) { - String name = device.getManufacturer(); - if (!name.equals("Generic") && // TODO define & use constants - !name.equals("User") && - device.getName().indexOf(name) == -1) { - name = " by " + name; - } else { - name = ""; - } - name = "AVD for " + device.getName() + name; + String name = "AVD for " + device.getDisplayName(); // sanitize the name - name = name.replaceAll("[^0-9a-zA-Z_-]+", " ").trim().replaceAll("[ _]+", "_"); + //name = name.replaceAll("[^0-9a-zA-Z_-]+", " ").trim().replaceAll("[ _]+", "_"); mWidgets.setText(Ctrl.TEXT_AVD_NAME, name); // Select the device @@ -1243,112 +1309,15 @@ private void fillInitialDeviceInfo(Device device) { * @return A non-null ISystemImage array. Can be empty. */ @NonNull - private ISystemImage[] getSystemImages(IAndroidTarget target) { - if (target != null) { - ISystemImage[] images = target.getSystemImages(); - - if ((images == null || images.length == 0) && !target.isPlatform()) { - // This is an add-on and it does not provide any system image. - - // Before LMP / Tools 23.0.4, the behavior was to provide the - // parent (platform) system-image using this code: - // - // images = target.getParent().getSystemImages(); - // - // After tools 23.0.4, the behavior is to NOT provide the - // platform system-image for the add-on. - } - - if (images != null) { - return images; - } - } - - return new ISystemImage[0]; - } - - // Code copied from DeviceMenuListener in ADT; unify post release - - private static final String NEXUS = "Nexus"; //$NON-NLS-1$ - private static final String GENERIC = "Generic"; //$NON-NLS-1$ - private static Pattern PATTERN = Pattern.compile( - "(\\d+\\.?\\d*)in (.+?)( \\(.*Nexus.*\\))?"); //$NON-NLS-1$ - - private static int nexusRank(Device device) { - @SuppressWarnings("deprecation") - String name = device.getName(); - if (name.endsWith(" One")) { //$NON-NLS-1$ - return 1; - } - if (name.endsWith(" S")) { //$NON-NLS-1$ - return 2; - } - if (name.startsWith("Galaxy")) { //$NON-NLS-1$ - return 3; - } - if (name.endsWith(" 7")) { //$NON-NLS-1$ - return 4; - } - if (name.endsWith(" 10")) { //$NON-NLS-1$ - return 5; - } - if (name.endsWith(" 4")) { //$NON-NLS-1$ - return 6; - } - - return 7; - } - - private static boolean isGeneric(Device device) { - return device.getManufacturer().equals(GENERIC); - } - - @SuppressWarnings("deprecation") - private static boolean isNexus(Device device) { - return device.getName().contains(NEXUS); + private Collection getSystemImages(IAndroidTarget target) { + return mSdkTargets.getSystemImages(target); } private static String getGenericLabel(Device d) { - // * Replace "'in'" with '"' (e.g. 2.7" QVGA instead of 2.7in QVGA) - // * Use the same precision for all devices (all but one specify decimals) - // * Add some leading space such that the dot ends up roughly in the - // same space - // * Add in screen resolution and density - @SuppressWarnings("deprecation") - String name = d.getName(); - if (name.equals("3.7 FWVGA slider")) { //$NON-NLS-1$ - // Fix metadata: this one entry doesn't have "in" like the rest of them - name = "3.7in FWVGA slider"; //$NON-NLS-1$ - } - - Matcher matcher = PATTERN.matcher(name); - if (matcher.matches()) { - String size = matcher.group(1); - String n = matcher.group(2); - int dot = size.indexOf('.'); - if (dot == -1) { - size = size + ".0"; - dot = size.length() - 2; - } - for (int i = 0; i < 2 - dot; i++) { - size = ' ' + size; - } - name = size + "\" " + n; - } - - return String.format(java.util.Locale.US, "%1$s (%2$s)", name, + return String.format(java.util.Locale.US, "%1$s (%2$s)", d.getDisplayName(), getResolutionString(d)); } - private static String getNexusLabel(Device d) { - @SuppressWarnings("deprecation") - String name = d.getName(); - Screen screen = d.getDefaultHardware().getScreen(); - float length = (float) screen.getDiagonalLength(); - return String.format(java.util.Locale.US, "%1$s (%3$s\", %2$s)", - name, getResolutionString(d), Float.toString(length)); - } - @Nullable private static String getResolutionString(Device device) { Screen screen = device.getDefaultHardware().getScreen(); @@ -1359,9 +1328,6 @@ private static String getResolutionString(Device device) { screen.getPixelDensity().getResourceValue()); } - //------- - - /** * AVD skin type. Order defines the order of the skin combo list. */ @@ -1484,5 +1450,47 @@ public void onRadioSdCardSizeChanged() { validatePage(); } + private ISystemImage getSystemImage(IAndroidTarget target, IdDisplay tag, String abiType) + { + if (target != null) + { + Collection systemImages = getSystemImages(target); + for (SystemImage sysImg : systemImages) { + if ((sysImg.getTag().equals(tag)) && (sysImg.getAbiType().equals(abiType))) { + return sysImg; + } + } + } + return null; + } + private Pair isAvdNameConflicting(String name) + { + boolean ignoreCase = SdkConstants.currentPlatform() == 2; + AvdInfo[] allAvdList = mAvdManager.getAllAvds(); + for (AvdInfo info : allAvdList) + { + String name2 = info.getName(); + if ((name2.equals(name)) || ((ignoreCase) && (name2.equalsIgnoreCase(name)))) + { + if (info.getStatus() == AvdInfo.AvdStatus.OK) { + return Pair.of(AvdConflict.CONFLICT_EXISTING_AVD, name2); + } + return Pair.of(AvdConflict.CONFLICT_INVALID_AVD, name2); + } + } + try + { + File file = AvdInfo.getDefaultIniFile(mAvdManager, name); + if (file.exists()) { + return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath()); + } + file = AvdInfo.getDefaultAvdFolder(mAvdManager, name, mSdkContext.getHandler().getFileOp(), false); + if (file.exists()) { + return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath()); + } + } + catch (AndroidLocationException e) {} + return Pair.of(AvdConflict.NO_CONFLICT, null); + } } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationSwtView.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationSwtView.java index dd2cef89..7dc1ad8d 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationSwtView.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdCreationSwtView.java @@ -18,11 +18,12 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; import com.android.sdkuilib.internal.widgets.AvdCreationPresenter.Ctrl; import com.android.sdkuilib.internal.widgets.AvdCreationPresenter.IWidgetAdapter; import com.android.sdkuilib.ui.GridDialog; +import com.android.sdkuilib.widgets.MessageBoxLog; +import org.eclipse.andmore.base.resources.ImageFactory; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java index 2f6b8800..b4172a43 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java @@ -16,35 +16,35 @@ package com.android.sdkuilib.internal.widgets; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.sdkuilib.ui.SwtBaseDialog; +import java.util.HashMap; +import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; -import java.util.HashMap; -import java.util.Map; +import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.ui.GridDataBuilder; +import com.android.sdkuilib.ui.GridLayoutBuilder; +import com.android.sdkuilib.ui.SwtBaseDialog; /** * Dialog displaying the details of an AVD. */ final class AvdDetailsDialog extends SwtBaseDialog { - private final AvdInfo mAvdInfo; + private final AvdAgent mAvdAgent; + private volatile int row = 0; - public AvdDetailsDialog(Shell shell, AvdInfo avdInfo) { + public AvdDetailsDialog(Shell shell, AvdAgent avdAgent) { super(shell, SWT.APPLICATION_MODAL, "AVD details"); - mAvdInfo = avdInfo; + mAvdAgent = avdAgent; } /** @@ -61,68 +61,59 @@ protected void createContents() { Composite c = new Composite(shell, SWT.NONE); c.setLayout(gl = new GridLayout(2, false)); gl.marginHeight = gl.marginWidth = 0; - c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - if (mAvdInfo != null) { - displayValue(c, "Name:", mAvdInfo.getName()); - displayValue(c, "CPU/ABI:", AvdInfo.getPrettyAbiType(mAvdInfo)); - - displayValue(c, "Path:", mAvdInfo.getDataFolderPath()); - - if (mAvdInfo.getStatus() != AvdStatus.OK) { - displayValue(c, "Error:", mAvdInfo.getErrorMessage()); + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + c.setLayoutData(gridData); + //Display display = c.getDisplay(); + //c.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + //c.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + + if (mAvdAgent != null) { + displayValue(c, "Name:", mAvdAgent.getAvd().getName()); + displayValue(c, "CPU/ABI:", mAvdAgent.getPrettyAbiType()); + displayValue(c, "Path:", mAvdAgent.getPath()); + if (mAvdAgent.getAvd().getStatus() != AvdStatus.OK) { + displayValue(c, "Error:", mAvdAgent.getAvd().getErrorMessage()); } else { - IAndroidTarget target = mAvdInfo.getTarget(); - AndroidVersion version = target.getVersion(); - displayValue(c, "Target:", String.format("%s (API level %s)", - target.getName(), version.getApiString())); - - // display some extra values. - Map properties = mAvdInfo.getProperties(); - if (properties != null) { - String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME); - if (skin != null) { - displayValue(c, "Skin:", skin); - } - - String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE); - if (sdcard == null) { - sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH); - } - if (sdcard != null) { - displayValue(c, "SD Card:", sdcard); - } - - String snapshot = properties.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - if (snapshot != null) { - displayValue(c, "Snapshot:", snapshot); - } - - // display other hardware - HashMap copy = new HashMap(properties); - // remove stuff we already displayed (or that we don't want to display) - copy.remove(AvdManager.AVD_INI_ABI_TYPE); - copy.remove(AvdManager.AVD_INI_CPU_ARCH); - copy.remove(AvdManager.AVD_INI_SKIN_NAME); - copy.remove(AvdManager.AVD_INI_SKIN_PATH); - copy.remove(AvdManager.AVD_INI_SDCARD_SIZE); - copy.remove(AvdManager.AVD_INI_SDCARD_PATH); - copy.remove(AvdManager.AVD_INI_IMAGES_1); - copy.remove(AvdManager.AVD_INI_IMAGES_2); - - if (copy.size() > 0) { - Label l = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL); - l.setLayoutData(new GridData( - GridData.FILL, GridData.CENTER, false, false, 2, 1)); - - c = new Composite(shell, SWT.NONE); - c.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - c.setLayoutData(new GridData(GridData.FILL_BOTH)); - - for (Map.Entry entry : copy.entrySet()) { - displayValue(c, entry.getKey() + ":", entry.getValue()); - } + displayValue(c, "Target:", mAvdAgent.getTargetDisplayName()); + displayValue(c, "Skin:", mAvdAgent.getSkin()); + String sdcard = mAvdAgent.getSdcard(); + if (!sdcard.isEmpty()) { + displayValue(c, "SD Card:", sdcard); + } + String snapshot = mAvdAgent.getSnapshot(); + if (!snapshot.isEmpty()) { + displayValue(c, "Snapshot:", snapshot); + } + // display other hardware + HashMap copy = new HashMap(mAvdAgent.getAvd().getProperties()); + // remove stuff we already displayed (or that we don't want to display) + copy.remove(AvdManager.AVD_INI_ABI_TYPE); + copy.remove(AvdManager.AVD_INI_CPU_ARCH); + copy.remove(AvdManager.AVD_INI_SKIN_NAME); + copy.remove(AvdManager.AVD_INI_SKIN_PATH); + copy.remove(AvdManager.AVD_INI_SDCARD_SIZE); + copy.remove(AvdManager.AVD_INI_SDCARD_PATH); + copy.remove(AvdManager.AVD_INI_IMAGES_1); + copy.remove(AvdManager.AVD_INI_IMAGES_2); + + if (copy.size() > 0) { + Label l = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL); + l.setLayoutData(new GridData( + GridData.FILL, GridData.HORIZONTAL_ALIGN_BEGINNING, false, false, 2, 1)); + //display = l.getDisplay(); + //l.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + c = new Composite(shell, SWT.NONE); + c.setLayout(gl = new GridLayout(2, false)); + //display = c.getDisplay(); + gl.marginHeight = gl.marginWidth = 0; + //c.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + c.setLayoutData(new GridData(GridData.FILL_BOTH)); + //c.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + //c.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + for (Map.Entry entry : copy.entrySet()) { + displayValue(c, entry.getKey() + ":", entry.getValue()); } } } @@ -147,14 +138,25 @@ protected void postCreate() { * @param label the label of the value to display. * @param value the string value to display. */ - private void displayValue(Composite parent, String label, String value) { - Label l = new Label(parent, SWT.NONE); - l.setText(label); - l.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); - - l = new Label(parent, SWT.NONE); - l.setText(value); - l.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false)); + private void displayValue(Composite parent, String key, String value) { + Label label = new Label(parent, SWT.LEFT); + label.setLayoutData(new GridData(GridData.FILL, GridData.VERTICAL_ALIGN_CENTER, false, false)); + Display display = label.getDisplay(); + if ((row & 1) == 0) { + label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + } + label.setText(key); + + label = new Label(parent, SWT.LEFT); + label.setLayoutData(new GridData(GridData.FILL, GridData.VERTICAL_ALIGN_CENTER, true, false)); + display = label.getDisplay(); + if ((row & 1) == 0) { + label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + } + label.setText(value); + ++row; } // End of hiding from SWT Designer diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdSelector.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdSelector.java index 7d05df97..49ff11ae 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdSelector.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdSelector.java @@ -16,31 +16,17 @@ package com.android.sdkuilib.internal.widgets; -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SystemImage; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.updater.SettingsController; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.icons.ImageFactory.Filter; -import com.android.sdkuilib.internal.repository.ui.AvdManagerWindowImpl1; -import com.android.sdkuilib.internal.tasks.ProgressTask; -import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.GrabProcessOutput; -import com.android.utils.GrabProcessOutput.IProcessOutput; -import com.android.utils.GrabProcessOutput.Wait; -import com.android.utils.ILogger; -import com.android.utils.NullLogger; +import java.awt.DisplayMode; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Formatter; +import java.util.Locale; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecorationOverlayIcon; @@ -49,12 +35,11 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -62,18 +47,37 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Formatter; -import java.util.Locale; +import com.android.SdkConstants; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.IdDisplay; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.ITask; +import com.android.sdkuilib.internal.repository.ITaskMonitor; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; +import com.android.sdkuilib.internal.repository.ui.AvdManagerWindowImpl1; +import com.android.sdkuilib.internal.tasks.ProgressTask; +import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; +import com.android.sdkuilib.ui.AvdDisplayMode; +import com.android.sdkuilib.ui.GridDialog; +import com.android.sdkuilib.widgets.MessageBoxLog; +import com.android.utils.GrabProcessOutput; +import com.android.utils.GrabProcessOutput.IProcessOutput; +import com.android.utils.GrabProcessOutput.Wait; +import com.android.utils.ILogger; +import com.android.utils.NullLogger; /** @@ -86,11 +90,9 @@ public final class AvdSelector { private static int NUM_COL = 2; - private final DisplayMode mDisplayMode; - + private final AvdDisplayMode mDisplayMode; + private final SdkTargets mSdkTargets; private AvdManager mAvdManager; - private final String mOsSdkPath; // TODO consider converting to File later - private Table mTable; private Button mDeleteButton; private Button mDetailsButton; @@ -111,43 +113,10 @@ public final class AvdSelector { private ImageFactory mImageFactory; private Image mBrokenImage; private Image mInvalidImage; - - private SettingsController mController; - - private final ILogger mSdkLog; + private final SdkContext mSdkContext; private boolean mInternalRefresh; - - /** - * The display mode of the AVD Selector. - */ - public static enum DisplayMode { - /** - * Manager mode. Invalid AVDs are displayed. Buttons to create/delete AVDs - */ - MANAGER, - - /** - * Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but - * there is a button to open the AVD Manager. - * In the "check" selection mode, checkboxes are displayed on each line - * and {@link AvdSelector#getSelected()} returns the line that is checked - * even if it is not the currently selected line. Only one line can - * be checked at once. - */ - SIMPLE_CHECK, - - /** - * Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but - * there is a button to open the AVD Manager. - * In the "select" selection mode, there are no checkboxes and - * {@link AvdSelector#getSelected()} returns the line currently selected. - * Only one line can be selected at once. - */ - SIMPLE_SELECTION, - } - /** * A filter to control the whether or not an AVD should be displayed by the AVD Selector. */ @@ -159,10 +128,10 @@ public interface IAvdFilter { /** * Called to decided whether an AVD should be displayed. - * @param avd the AVD to test. + * @param avdAgent Agent containing the AVD to test. * @return true if the AVD should be displayed. */ - boolean accept(AvdInfo avd); + boolean accept(AvdAgent avdAgent); /** * Called after {@link #accept(AvdInfo)} has been called on all the AVDs. @@ -187,9 +156,9 @@ public void prepare() { } @Override - public boolean accept(AvdInfo avd) { - if (avd != null) { - return mTarget.canRunOn(avd.getTarget()); + public boolean accept(AvdAgent avdAgent) { + if (avdAgent != null) { + return mTarget.canRunOn(avdAgent.getTarget()); } return false; @@ -208,27 +177,24 @@ public void cleanup() { * {@link IAndroidTarget} will be displayed. * * @param parent The parent composite where the selector will be added. - * @param osSdkPath The SDK root path. When not null, enables the start button to start - * an emulator on a given AVD. + * @param sdkContext SDK handler and repo manager * @param manager the AVD manager. * @param filter When non-null, will allow filtering the AVDs to display. * @param displayMode The display mode ({@link DisplayMode}). * @param sdkLog The logger. Cannot be null. */ public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, + SdkContext sdkContext, IAvdFilter filter, - DisplayMode displayMode, - ILogger sdkLog) { - mOsSdkPath = osSdkPath; - mAvdManager = manager; + AvdDisplayMode displayMode) { + mSdkTargets = new SdkTargets(sdkContext); + mSdkContext = sdkContext; + mAvdManager = sdkContext.getAvdManager(); mTargetFilter = filter; mDisplayMode = displayMode; - mSdkLog = sdkLog; // get some bitmaps. - mImageFactory = new ImageFactory(parent.getDisplay()); + mImageFactory = mSdkContext.getSdkHelper().getImageFactory(); mBrokenImage = mImageFactory.getImageByName("warning_icon16.png"); mInvalidImage = mImageFactory.getImageByName("reject_icon16.png"); @@ -239,15 +205,9 @@ public AvdSelector(Composite parent, gl.marginHeight = gl.marginWidth = 0; group.setLayoutData(new GridData(GridData.FILL_BOTH)); group.setFont(parent.getFont()); - group.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent arg0) { - mImageFactory.dispose(); - } - }); int style = SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER; - if (displayMode == DisplayMode.SIMPLE_CHECK) { + if (displayMode == AvdDisplayMode.SIMPLE_CHECK) { style |= SWT.CHECK; } mTable = new Table(group, style); @@ -261,7 +221,7 @@ public void widgetDisposed(DisposeEvent arg0) { buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL)); buttons.setFont(group.getFont()); - if (displayMode == DisplayMode.MANAGER) { + if (displayMode == AvdDisplayMode.MANAGER) { mNewButton = new Button(buttons, SWT.PUSH | SWT.FLAT); mNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mNewButton.setText("Create..."); @@ -289,7 +249,7 @@ public void widgetSelected(SelectionEvent arg0) { @SuppressWarnings("unused") Label spacing = new Label(buttons, SWT.NONE); - if (displayMode == DisplayMode.MANAGER) { + if (displayMode == AvdDisplayMode.MANAGER) { mEditButton = new Button(buttons, SWT.PUSH | SWT.FLAT); mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mEditButton.setText("Edit..."); @@ -349,7 +309,7 @@ public void widgetSelected(SelectionEvent arg0) { } }); - if (displayMode != DisplayMode.MANAGER) { + if (displayMode != AvdDisplayMode.MANAGER) { mManagerButton = new Button(buttons, SWT.PUSH | SWT.FLAT); mManagerButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mManagerButton.setText("Manager..."); @@ -401,14 +361,13 @@ public void widgetSelected(SelectionEvent e) { * @param sdkLog The logger. Cannot be null. */ public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, - DisplayMode displayMode, - ILogger sdkLog) { - this(parent, osSdkPath, manager, (IAvdFilter)null /* filter */, displayMode, sdkLog); + SdkContext sdkContext, + AvdDisplayMode displayMode) { + this(parent, sdkContext, (IAvdFilter)null /* filter */, displayMode); } /** + * *** NOT REFERENCED *** * Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}, filtered * by an {@link IAndroidTarget}. *

Only the {@link AvdInfo} able to run applications developed for the given @@ -421,20 +380,10 @@ public AvdSelector(Composite parent, * @param sdkLog The logger. Cannot be null. */ public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, + SdkContext sdkContext, IAndroidTarget filter, - DisplayMode displayMode, - ILogger sdkLog) { - this(parent, osSdkPath, manager, new TargetBasedFilter(filter), displayMode, sdkLog); - } - - /** - * Sets an optional SettingsController. - * @param controller the controller. - */ - public void setSettingsController(SettingsController controller) { - mController = controller; + AvdDisplayMode displayMode) { + this(parent, sdkContext, new TargetBasedFilter(filter), displayMode); } /** @@ -479,7 +428,7 @@ public boolean refresh(boolean reload) { } } - AvdInfo selected = getSelected(); + AvdAgent selected = getSelected(); fillTable(mTable); setSelection(selected); return true; @@ -544,7 +493,21 @@ public void setSelectionListener(SelectionListener selectionListener) { mSelectionListener = selectionListener; } - /** + /** + * Sets the current target selection. + *

+ * If the selection is actually changed, this will invoke the selection listener + * (if any) with a null event. + * + * @param target the target to be selected. Use null to deselect everything. + * @return true if the target could be selected, false otherwise. + */ + public void setSelection(AvdInfo avd) { + AvdAgent target = new AvdAgent(mSdkTargets.getTargetForSysImage((SystemImage)avd.getSystemImage()), avd); + setSelection(target); + } + + /** * Sets the current target selection. *

* If the selection is actually changed, this will invoke the selection listener @@ -553,15 +516,16 @@ public void setSelectionListener(SelectionListener selectionListener) { * @param target the target to be selected. Use null to deselect everything. * @return true if the target could be selected, false otherwise. */ - public boolean setSelection(AvdInfo target) { + public boolean setSelection(AvdAgent target) { boolean found = false; boolean modified = false; int selIndex = mTable.getSelectionIndex(); int index = 0; for (TableItem i : mTable.getItems()) { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { - if ((AvdInfo) i.getData() == target) { + AvdAgent avdAgent = (AvdAgent)i.getData(); + if (mDisplayMode == AvdDisplayMode.SIMPLE_CHECK) { + if (avdAgent == target) { found = true; if (!i.getChecked()) { modified = true; @@ -572,7 +536,7 @@ public boolean setSelection(AvdInfo target) { i.setChecked(false); } } else { - if ((AvdInfo) i.getData() == target) { + if (avdAgent == target) { found = true; if (index != selIndex) { mTable.setSelection(index); @@ -584,13 +548,10 @@ public boolean setSelection(AvdInfo target) { index++; } } - if (modified && mSelectionListener != null) { mSelectionListener.widgetSelected(null); } - enableActionButtons(); - return found; } @@ -600,20 +561,19 @@ public boolean setSelection(AvdInfo target) { * * @return The currently selected item or null. */ - public AvdInfo getSelected() { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { + public AvdAgent getSelected() { + if (mDisplayMode == AvdDisplayMode.SIMPLE_CHECK) { for (TableItem i : mTable.getItems()) { if (i.getChecked()) { - return (AvdInfo) i.getData(); + return (AvdAgent) i.getData(); } } } else { int selIndex = mTable.getSelectionIndex(); if (selIndex >= 0) { - return (AvdInfo) mTable.getItem(selIndex).getData(); + return (AvdAgent) mTable.getItem(selIndex).getData(); } } - return null; } @@ -709,7 +669,7 @@ public void widgetSelected(SelectionEvent e) { public void widgetDefaultSelected(SelectionEvent e) { if (e.item instanceof TableItem) { TableItem i = (TableItem) e.item; - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { + if (mDisplayMode == AvdDisplayMode.SIMPLE_CHECK) { i.setChecked(true); } enforceSingleSelection(i); @@ -717,7 +677,7 @@ public void widgetDefaultSelected(SelectionEvent e) { } // whether or not we display details. default: true when not in SIMPLE_CHECK mode. - boolean showDetails = mDisplayMode != DisplayMode.SIMPLE_CHECK; + boolean showDetails = mDisplayMode != AvdDisplayMode.SIMPLE_CHECK; if (mSelectionListener != null) { mSelectionListener.widgetDefaultSelected(e); @@ -736,7 +696,7 @@ public void widgetDefaultSelected(SelectionEvent e) { * This makes the chekboxes act as radio buttons. */ private void enforceSingleSelection(TableItem item) { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { + if (mDisplayMode == AvdDisplayMode.SIMPLE_CHECK) { if (item.getChecked()) { Table parentTable = item.getParent(); for (TableItem i2 : parentTable.getItems()) { @@ -757,9 +717,10 @@ private void enforceSingleSelection(TableItem item) { * The table columns are: *

    *
  • column 0: sdk name - *
  • column 1: sdk vendor - *
  • column 2: sdk api name - *
  • column 3: sdk version + *
  • column 1: sdk target + *
  • column 2: sdk platform + *
  • column 3: sdk API level + *
  • column 4: CPU/ABI *
*/ private void fillTable(final Table table) { @@ -768,13 +729,12 @@ private void fillTable(final Table table) { // get the AVDs AvdInfo avds[] = null; if (mAvdManager != null) { - if (mDisplayMode == DisplayMode.MANAGER) { + if (mDisplayMode == AvdDisplayMode.MANAGER) { avds = mAvdManager.getAllAvds(); } else { avds = mAvdManager.getValidAvds(); } } - if (avds != null && avds.length > 0) { Arrays.sort(avds, new Comparator() { @Override @@ -782,19 +742,17 @@ public int compare(AvdInfo o1, AvdInfo o2) { return o1.compareTo(o2); } }); - table.setEnabled(true); - if (mTargetFilter != null) { mTargetFilter.prepare(); } - for (AvdInfo avd : avds) { - if (mTargetFilter == null || mTargetFilter.accept(avd)) { + AvdAgent avdAgent = new AvdAgent(mSdkTargets.getTargetForSysImage((SystemImage)avd.getSystemImage()), avd); + if (mTargetFilter == null || mTargetFilter.accept(avdAgent)) { TableItem item = new TableItem(table, SWT.NONE); - item.setData(avd); + item.setData(avdAgent); item.setText(0, avd.getName()); - if (mDisplayMode == DisplayMode.MANAGER) { + if (mDisplayMode == AvdDisplayMode.MANAGER) { AvdStatus status = avd.getStatus(); boolean isOk = status == AvdStatus.OK; @@ -804,26 +762,16 @@ public int compare(AvdInfo o1, AvdInfo o2) { Image img = getTagImage(avd.getTag(), isOk, isRepair, isInvalid); item.setImage(0, img); } - IAndroidTarget target = avd.getTarget(); - if (target != null) { - item.setText(1, target.getFullName()); - item.setText(2, target.getVersionName()); - item.setText(3, target.getVersion().getApiString()); - item.setText(4, AvdInfo.getPrettyAbiType(avd)); - } else { - item.setText(1, "?"); - item.setText(2, "?"); - item.setText(3, "?"); - item.setText(4, "?"); - } + item.setText(1, avdAgent.getTargetFullName()); + item.setText(2, avdAgent.getTargetVersionName()); + item.setText(3, avd.getAndroidVersion().getApiString()); + item.setText(4, AvdInfo.getPrettyAbiType(avd)); } } - if (mTargetFilter != null) { mTargetFilter.cleanup(); } } - if (table.getItemCount() == 0) { table.setEnabled(false); TableItem item = new TableItem(table, SWT.NONE); @@ -849,20 +797,18 @@ private Image getTagImage(IdDisplay tag, (isRepair ? 1 : 0), (isInvalid ? 1 : 0), fname); - return mImageFactory.getImageByName(fname, kname, new Filter() { + if (isOk) + return mImageFactory.getImageByName(fname); + + return mImageFactory.getImageByName(fname, kname, new ImageFactory.ImageEditor() { @Override - public Image filter(Image source) { - // We don't need an overlay for good AVDs. - if (isOk) { - return source; - } - + public ImageData edit(Image source) { Image overlayImg = isRepair ? mBrokenImage : mInvalidImage; ImageDescriptor overlayDesc = ImageDescriptor.createFromImage(overlayImg); DecorationOverlayIcon overlaid = new DecorationOverlayIcon(source, overlayDesc, IDecoration.BOTTOM_RIGHT); - return overlaid.createImage(); + return overlaid.getImageData(); } }); } @@ -873,19 +819,17 @@ public Image filter(Image source) { * Unlike {@link #getSelected()} this will always return the item being selected * in the list, ignoring the check boxes state in {@link DisplayMode#SIMPLE_CHECK} mode. */ - private AvdInfo getTableSelection() { + private AvdAgent getTableSelection() { int selIndex = mTable.getSelectionIndex(); if (selIndex >= 0) { - return (AvdInfo) mTable.getItem(selIndex).getData(); + return (AvdAgent) mTable.getItem(selIndex).getData(); } - return null; } /** * Updates the enable state of the Details, Start, Delete and Update buttons. */ - @SuppressWarnings("null") private void enableActionButtons() { if (mIsEnabled == false) { mDetailsButton.setEnabled(false); @@ -901,13 +845,12 @@ private void enableActionButtons() { mRepairButton.setEnabled(false); } } else { - AvdInfo selection = getTableSelection(); + AvdAgent selection = getTableSelection(); boolean hasSelection = selection != null; mDetailsButton.setEnabled(hasSelection); - mStartButton.setEnabled(mOsSdkPath != null && - hasSelection && - selection.getStatus() == AvdStatus.OK); + mStartButton.setEnabled(hasSelection && + selection.getAvd().getStatus() == AvdStatus.OK); if (mEditButton != null) { mEditButton.setEnabled(hasSelection); @@ -916,62 +859,59 @@ private void enableActionButtons() { mDeleteButton.setEnabled(hasSelection); } if (mRepairButton != null) { - mRepairButton.setEnabled(hasSelection && isAvdRepairable(selection.getStatus())); + mRepairButton.setEnabled(hasSelection && isAvdRepairable(selection.getAvd().getStatus())); } } } private void onNew() { AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, + mSdkContext, + mSdkTargets, null); if (dlg.open() == Window.OK) { - refresh(false /*reload*/); + refresh(false); //reload } } - @SuppressWarnings("deprecation") private void onEdit() { - AvdInfo avdInfo = getTableSelection(); + AvdAgent avdAgent = getTableSelection(); GridDialog dlg; - if (!avdInfo.getDeviceName().isEmpty()) { + if (!avdAgent.getAvd().getDeviceName().isEmpty()) { dlg = new AvdCreationDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, - avdInfo); - } else { - dlg = new LegacyAvdEditDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, - avdInfo); - } - - - if (dlg.open() == Window.OK) { - refresh(false /*reload*/); + mSdkContext, + mSdkTargets, + avdAgent); + if (dlg.open() == Window.OK) { + refresh(false); //reload + } else { + // create a dialog with ok button and a warning icon + MessageBox dialog = + new MessageBox(mTable.getShell(), SWT.ICON_WARNING| SWT.OK); + dialog.setText("Legacy device not supported"); + dialog.setMessage(avdAgent.getAvd().getName() + " has is assigned a legacy device no longer supported by the Android SDK"); + // open dialog and await user selection + dialog.open(); + } } } private void onDetails() { - AvdInfo avdInfo = getTableSelection(); + AvdAgent avdAgent = getTableSelection(); - AvdDetailsDialog dlg = new AvdDetailsDialog(mTable.getShell(), avdInfo); + AvdDetailsDialog dlg = new AvdDetailsDialog(mTable.getShell(), avdAgent); dlg.open(); } private void onDelete() { - final AvdInfo avdInfo = getTableSelection(); + final AvdAgent avdAgent = getTableSelection(); // get the current Display final Display display = mTable.getDisplay(); // check if the AVD is running - if (mAvdManager.isAvdRunning(avdInfo)) { + if (mAvdManager.isAvdRunning(avdAgent.getAvd(), mSdkContext.getSdkLog())) { display.asyncExec(new Runnable() { @Override public void run() { @@ -980,7 +920,7 @@ public void run() { "Delete Android Virtual Device", String.format( "The Android Virtual Device '%1$s' is currently running in an emulator and cannot be deleted.", - avdInfo.getName())); + avdAgent.getAvd().getName())); } }); return; @@ -996,7 +936,7 @@ public void run() { "Delete Android Virtual Device", String.format( "Please confirm that you want to delete the Android Virtual Device named '%s'. This operation cannot be reverted.", - avdInfo.getName())); + avdAgent.getAvd().getName())); } }); @@ -1004,19 +944,19 @@ public void run() { return; } - // log for this action. - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { + ILogger log = null; + // log for this action. + if (log == null || log instanceof MessageBoxLog) { // If the current logger is a message box, we use our own (to make sure // to display errors right away and customize the title). log = new MessageBoxLog( - String.format("Result of deleting AVD '%s':", avdInfo.getName()), + String.format("Result of deleting AVD '%s':", avdAgent.getAvd().getName()), display, false /*logErrorsOnly*/); } // delete the AVD - boolean success = mAvdManager.deleteAvd(avdInfo, log); + boolean success = mAvdManager.deleteAvd(avdAgent.getAvd(), log); // display the result if (log instanceof MessageBoxLog) { @@ -1034,38 +974,37 @@ public void run() { * For now this only supports fixing the wrong value in image.sysdir.* */ private void onRepair() { - final AvdInfo avdInfo = getTableSelection(); + final AvdAgent avdAgent = getTableSelection(); // get the current Display final Display display = mTable.getDisplay(); - // log for this action. - ILogger log = mSdkLog; + ILogger log = null; if (log == null || log instanceof MessageBoxLog) { // If the current logger is a message box, we use our own (to make sure // to display errors right away and customize the title). log = new MessageBoxLog( - String.format("Result of updating AVD '%s':", avdInfo.getName()), + String.format("Result of updating AVD '%s':", avdAgent.getAvd().getName()), display, false /*logErrorsOnly*/); } - if (avdInfo.getStatus() == AvdStatus.ERROR_IMAGE_DIR) { + if (avdAgent.getAvd().getStatus() == AvdStatus.ERROR_IMAGE_DIR) { // delete the AVD try { - mAvdManager.updateAvd(avdInfo, log); + mAvdManager.updateAvd(avdAgent.getAvd(), avdAgent.getAvd().getProperties()); } catch (IOException e) { - log.error(e, null); + log.error(e, null); } refresh(false /*reload*/); - } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_CHANGED) { + } else if (avdAgent.getAvd().getStatus() == AvdStatus.ERROR_DEVICE_CHANGED) { try { - mAvdManager.updateDeviceChanged(avdInfo, log); + mAvdManager.updateDeviceChanged(avdAgent.getAvd(), log); } catch (IOException e) { log.error(e, null); } refresh(false /*reload*/); - } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_MISSING) { + } else if (avdAgent.getAvd().getStatus() == AvdStatus.ERROR_DEVICE_MISSING) { onEdit(); } } @@ -1076,7 +1015,7 @@ private void onAvdManager() { Display display = mTable.getDisplay(); // log for this action. - ILogger log = mSdkLog; + ILogger log = null; if (log == null || log instanceof MessageBoxLog) { // If the current logger is a message box, we use our own (to make sure // to display errors right away and customize the title). @@ -1087,7 +1026,7 @@ private void onAvdManager() { AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1( mTable.getShell(), log, - mOsSdkPath, + mSdkContext, AvdInvocationContext.DIALOG); win.open(); @@ -1101,24 +1040,23 @@ private void onAvdManager() { } private void onStart() { - AvdInfo avdInfo = getTableSelection(); + AvdAgent avdAgent = getTableSelection(); - if (avdInfo == null || mOsSdkPath == null) { + if (avdAgent == null) { return; } - + File osSdkPath = mSdkContext.getLocation(); AvdStartDialog dialog = new AvdStartDialog( mTable.getShell(), - avdInfo, - new File(mOsSdkPath), - mController, - mSdkLog); + avdAgent, + osSdkPath, + mSdkContext.getSdkLog()); if (dialog.open() == Window.OK) { - String path = mOsSdkPath + File.separator + String path = osSdkPath + File.separator + SdkConstants.OS_SDK_TOOLS_FOLDER + SdkConstants.FN_EMULATOR; - final String avdName = avdInfo.getName(); + final String avdName = avdAgent.getAvd().getName(); // build the command line based on the available parameters. ArrayList list = new ArrayList(); @@ -1260,4 +1198,5 @@ private boolean isAvdRepairable(AvdStatus avdStatus) { || avdStatus == AvdStatus.ERROR_DEVICE_CHANGED || avdStatus == AvdStatus.ERROR_DEVICE_MISSING; } + } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdStartDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdStartDialog.java index 00eb1aa6..a8dfe645 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdStartDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/AvdStartDialog.java @@ -20,10 +20,10 @@ import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.updater.SettingsController; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; import com.android.sdkuilib.ui.GridDialog; +import com.android.sdkuilib.ui.ResolutionChooserDialog; import com.android.utils.ILogger; -import com.android.utils.SdkUtils; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.window.Window; @@ -78,7 +78,6 @@ final class AvdStartDialog extends GridDialog { private final AvdInfo mAvd; private final File mSdkLocation; - private final SettingsController mSettingsController; private final DeviceManager mDeviceManager; private Text mScreenSize; @@ -98,12 +97,10 @@ final class AvdStartDialog extends GridDialog { private boolean mSnapshotLaunch = true; private Button mSnapshotLaunchCheckbox; - AvdStartDialog(Shell parentShell, AvdInfo avd, File sdkLocation, - SettingsController settingsController, ILogger sdkLog) { + AvdStartDialog(Shell parentShell, AvdAgent avdAgent, File sdkLocation, ILogger sdkLog) { super(parentShell, 2, false); - mAvd = avd; + mAvd = avdAgent.getAvd(); mSdkLocation = sdkLocation; - mSettingsController = settingsController; mDeviceManager = DeviceManager.createInstance(mSdkLocation, sdkLog); if (mAvd == null) { throw new IllegalArgumentException("avd cannot be null"); @@ -330,12 +327,6 @@ protected void okPressed() { String dpi = mMonitorDpi.getText(); if (dpi.length() > 0) { sMonitorDpi = Integer.parseInt(dpi); - - // if there is a setting controller, save it - if (mSettingsController != null) { - mSettingsController.setMonitorDensity(sMonitorDpi); - mSettingsController.saveSettings(); - } } // now the scale factor @@ -434,9 +425,6 @@ private void setScale(float scale) { * can tell us. */ private int getMonitorDpi() { - if (mSettingsController != null) { - sMonitorDpi = mSettingsController.getSettings().getMonitorDensity(); - } if (sMonitorDpi == -1) { // first time? try to get a value sMonitorDpi = Toolkit.getDefaultToolkit().getScreenResolution(); diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java index 263ca210..bf482e25 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java @@ -44,7 +44,7 @@ import com.android.sdklib.devices.Software; import com.android.sdklib.devices.State; import com.android.sdklib.devices.Storage; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; +import org.eclipse.andmore.base.resources.ImageFactory; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridDialog; import com.android.sdkuilib.ui.GridLayoutBuilder; @@ -68,7 +68,6 @@ import org.eclipse.swt.widgets.Text; import java.util.Collection; -import java.util.List; import java.util.Map; public class DeviceCreationDialog extends GridDialog { diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java deleted file mode 100644 index b471cc79..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2009 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.sdkuilib.internal.widgets; - -import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty; -import com.android.sdklib.internal.avd.HardwareProperties.HardwarePropertyType; -import com.android.sdkuilib.ui.GridDialog; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; - -/** - * Dialog to choose a hardware property - */ -class HardwarePropertyChooser extends GridDialog { - - private final Map mProperties; - private final Collection mExceptProperties; - private HardwareProperty mChosenProperty; - private Label mTypeLabel; - private Label mDescriptionLabel; - - HardwarePropertyChooser(Shell parentShell, - Map properties, - Collection exceptProperties) { - super(parentShell, 2, false); - mProperties = properties; - mExceptProperties = exceptProperties; - } - - public HardwareProperty getProperty() { - return mChosenProperty; - } - - @Override - public void createDialogContent(Composite parent) { - Label l = new Label(parent, SWT.NONE); - l.setText("Property:"); - - final Combo c = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); - // simple list for index->name resolution. - final ArrayList indexToName = new ArrayList(); - - // Sort the combo entries by display name if available, otherwise by hardware name. - Set> entries = - new TreeSet>( - new Comparator>() { - @Override - public int compare(Entry entry0, - Entry entry1) { - String s0 = entry0.getValue().getAbstract(); - String s1 = entry1.getValue().getAbstract(); - if (s0 != null && s1 != null) { - return s0.compareTo(s1); - } - return entry0.getKey().compareTo(entry1.getKey()); - } - }); - entries.addAll(mProperties.entrySet()); - - for (Entry entry : entries) { - if (entry.getValue().isValidForUi() && - mExceptProperties.contains(entry.getKey()) == false) { - c.add(entry.getValue().getAbstract()); - indexToName.add(entry.getKey()); - } - } - boolean hasValues = true; - if (indexToName.size() == 0) { - hasValues = false; - c.add("No properties"); - c.select(0); - c.setEnabled(false); - } - - c.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - int index = c.getSelectionIndex(); - String name = indexToName.get(index); - processSelection(name, true /* pack */); - } - }); - - l = new Label(parent, SWT.NONE); - l.setText("Type:"); - - mTypeLabel = new Label(parent, SWT.NONE); - - l = new Label(parent, SWT.NONE); - l.setText("Description:"); - - mDescriptionLabel = new Label(parent, SWT.NONE); - - if (hasValues) { - c.select(0); - processSelection(indexToName.get(0), false /* pack */); - } - } - - private void processSelection(String name, boolean pack) { - mChosenProperty = name == null ? null : mProperties.get(name); - - String type = "Unknown"; - String desc = "Unknown"; - - if (mChosenProperty != null) { - desc = mChosenProperty.getDescription(); - HardwarePropertyType vt = mChosenProperty.getType(); - if (vt != null) { - type = vt.getName(); - } - } - - mTypeLabel.setText(type); - mDescriptionLabel.setText(desc); - - if (pack) { - getShell().pack(); - } - } - -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java deleted file mode 100644 index ee892637..00000000 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java +++ /dev/null @@ -1,1439 +0,0 @@ -/* - * Copyright (C) 2009 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.sdkuilib.internal.widgets; - -import com.android.SdkConstants; -import com.android.io.FileWrapper; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SystemImage; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.avd.AvdManager.AvdConflict; -import com.android.sdklib.internal.avd.HardwareProperties; -import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdklib.repository.descriptors.IdDisplay; -import com.android.sdklib.repository.local.LocalSdk; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.ILogger; -import com.android.utils.Pair; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.jface.viewers.CellLabelProvider; -import org.eclipse.jface.viewers.ComboBoxCellEditor; -import org.eclipse.jface.viewers.EditingSupport; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.TextCellEditor; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerCell; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.regex.Matcher; - -/** - * AVD creation or edit dialog. - * - * @deprecated Replaced by {@link AvdCreationDialog} - */ -final class LegacyAvdEditDialog extends GridDialog { - - private static final String ABI_SYS_IMG_DATA_KEY = "systemImagesData"; //$NON-NLS-1$ - - private final AvdManager mAvdManager; - private final TreeMap mCurrentTargets = - new TreeMap(); - - private final Map mHardwareMap; - private final Map mProperties = new HashMap(); - // a list of user-edited properties. - private final ArrayList mEditedProperties = new ArrayList(); - private final ImageFactory mImageFactory; - private final ILogger mSdkLog; - /** - * The original AvdInfo if we're editing an existing AVD. - * Null when we're creating a new AVD. - */ - private final AvdInfo mEditAvdInfo; - - private Text mAvdName; - private Combo mTargetCombo; - - private Combo mTagAbiCombo; - private String mAbiType; - - private Button mSdCardSizeRadio; - private Text mSdCardSize; - private Combo mSdCardSizeCombo; - - private Text mSdCardFile; - private Button mBrowseSdCard; - private Button mSdCardFileRadio; - - private Button mSnapshotCheck; - - private Button mSkinListRadio; - private Combo mSkinCombo; - - private Button mSkinSizeRadio; - private Text mSkinSizeWidth; - private Text mSkinSizeHeight; - - private TableViewer mHardwareViewer; - private Button mDeleteHardwareProp; - - private Button mForceCreation; - private Button mOkButton; - private Label mStatusIcon; - private Label mStatusLabel; - private Composite mStatusComposite; - - /** - * {@link VerifyListener} for {@link Text} widgets that should only contains numbers. - */ - private final VerifyListener mDigitVerifier = new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - int count = event.text.length(); - for (int i = 0 ; i < count ; i++) { - char c = event.text.charAt(i); - if (c < '0' || c > '9') { - event.doit = false; - return; - } - } - } - }; - - /** - * Callback when the AVD name is changed. - * When creating a new AVD, enables the force checkbox if the name is a duplicate. - * When editing an existing AVD, it's OK for the name to match the existing AVD. - */ - private class CreateNameModifyListener implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - String name = mAvdName.getText().trim(); - if (mEditAvdInfo == null || !name.equals(mEditAvdInfo.getName())) { - // Case where we're creating a new AVD or editing an existing one - // and the AVD name has been changed... check for name uniqueness. - - Pair conflict = mAvdManager.isAvdNameConflicting(name); - if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) { - // If we're changing the state from disabled to enabled, make sure - // to uncheck the button, to force the user to voluntarily re-enforce it. - // This happens when editing an existing AVD and changing the name from - // the existing AVD to another different existing AVD. - if (!mForceCreation.isEnabled()) { - mForceCreation.setEnabled(true); - mForceCreation.setSelection(false); - } - } else { - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - } else { - // Case where we're editing an existing AVD with the name unchanged. - - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - validatePage(); - } - } - - /** - * {@link ModifyListener} used for live-validation of the fields content. - */ - private class ValidateListener extends SelectionAdapter implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - validatePage(); - } - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - } - - /** - * Creates the dialog. Caller should then use {@link Window#open()} and - * refresh if the status is {@link Window#OK}. - * - * @param parentShell The parent shell. - * @param avdManager The existing {@link AvdManager} to use. Must not be null. - * @param imageFactory An existing {@link ImageFactory} to use. Must not be null. - * @param log An existing {@link ILogger} where output will go. Must not be null. - * @param editAvdInfo An optional {@link AvdInfo}. When null, the dialog is used - * to create a new AVD. When non-null, the dialog is used to edit this AVD. - */ - protected LegacyAvdEditDialog(Shell parentShell, - AvdManager avdManager, - ImageFactory imageFactory, - ILogger log, - AvdInfo editAvdInfo) { - super(parentShell, 2, false); - mAvdManager = avdManager; - mImageFactory = imageFactory; - mSdkLog = log; - mEditAvdInfo = editAvdInfo; - - File hardwareDefs = null; - - LocalSdk localSdk = avdManager.getLocalSdk(); - if (localSdk != null) { - File sdkPath = localSdk.getLocation(); - if (sdkPath != null) { - hardwareDefs = new File(new File(sdkPath, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER), - SdkConstants.FN_HARDWARE_INI); - } - } - - if (hardwareDefs == null) { - log.error(null, "Failed to load file %s from SDK", SdkConstants.FN_HARDWARE_INI); - mHardwareMap = new HashMap(); - } else { - mHardwareMap = HardwareProperties.parseHardwareDefinitions( - hardwareDefs, null /*sdkLog*/); - } - } - - @Override - public void create() { - super.create(); - - Point p = getShell().getSize(); - if (p.x < 400) { - p.x = 400; - } - getShell().setSize(p); - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - getShell().setText(mEditAvdInfo == null ? "Create new Android Virtual Device (AVD)" - : "Edit Android Virtual Device (AVD)"); - - mOkButton = getButton(IDialogConstants.OK_ID); - - fillExistingAvdInfo(); - validatePage(); - - return control; - } - - @Override - public void createDialogContent(final Composite parent) { - GridData gd; - GridLayout gl; - - Label label = new Label(parent, SWT.NONE); - label.setText("Name:"); - String tooltip = "Name of the new Android Virtual Device"; - label.setToolTipText(tooltip); - - mAvdName = new Text(parent, SWT.BORDER); - mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mAvdName.addModifyListener(new CreateNameModifyListener()); - mAvdName.setToolTipText(tooltip); - - label = new Label(parent, SWT.NONE); - label.setText("Target:"); - tooltip = "The version of Android to use in the virtual device"; - label.setToolTipText(tooltip); - - mTargetCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTargetCombo.setToolTipText(tooltip); - mTargetCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - reloadSkinCombo(); - reloadTagAbiCombo(); - validatePage(); - } - }); - - //ABI group - label = new Label(parent, SWT.NONE); - label.setText("CPU/ABI:"); - tooltip = "The CPU/ABI to use in the virtual device"; - label.setToolTipText(tooltip); - - mTagAbiCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mTagAbiCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTagAbiCombo.setToolTipText(tooltip); - mTagAbiCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - }); - mTagAbiCombo.setEnabled(false); - - // --- sd card group - label = new Label(parent, SWT.NONE); - label.setText("SD Card:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group sdCardGroup = new Group(parent, SWT.NONE); - sdCardGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - sdCardGroup.setLayout(new GridLayout(3, false)); - - mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardSizeRadio.setText("Size:"); - mSdCardSizeRadio.setToolTipText("Create a new SD Card file"); - mSdCardSizeRadio.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - boolean sizeMode = mSdCardSizeRadio.getSelection(); - enableSdCardWidgets(sizeMode); - validatePage(); - } - }); - - ValidateListener validateListener = new ValidateListener(); - - mSdCardSize = new Text(sdCardGroup, SWT.BORDER); - mSdCardSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardSize.addVerifyListener(mDigitVerifier); - mSdCardSize.addModifyListener(validateListener); - mSdCardSize.setToolTipText("Size of the new SD Card file (must be at least 9 MiB)"); - - mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY); - mSdCardSizeCombo.add("KiB"); - mSdCardSizeCombo.add("MiB"); - mSdCardSizeCombo.add("GiB"); - mSdCardSizeCombo.select(1); - mSdCardSizeCombo.addSelectionListener(validateListener); - - mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardFileRadio.setText("File:"); - mSdCardFileRadio.setToolTipText("Use an existing file for the SD Card"); - - mSdCardFile = new Text(sdCardGroup, SWT.BORDER); - mSdCardFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardFile.addModifyListener(validateListener); - mSdCardFile.setToolTipText("File to use for the SD Card"); - - mBrowseSdCard = new Button(sdCardGroup, SWT.PUSH); - mBrowseSdCard.setText("Browse..."); - mBrowseSdCard.setToolTipText("Select the file to use for the SD Card"); - mBrowseSdCard.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onBrowseSdCard(); - validatePage(); - } - }); - - mSdCardSizeRadio.setSelection(true); - enableSdCardWidgets(true); - - // --- snapshot group - - label = new Label(parent, SWT.NONE); - label.setText("Snapshot:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group snapshotGroup = new Group(parent, SWT.NONE); - snapshotGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - snapshotGroup.setLayout(new GridLayout(3, false)); - - mSnapshotCheck = new Button(snapshotGroup, SWT.CHECK); - mSnapshotCheck.setText("Enabled"); - mSnapshotCheck.setToolTipText( - "Emulator's state will be persisted between emulator executions"); - - // --- skin group - label = new Label(parent, SWT.NONE); - label.setText("Skin:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group skinGroup = new Group(parent, SWT.NONE); - skinGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - skinGroup.setLayout(new GridLayout(4, false)); - - mSkinListRadio = new Button(skinGroup, SWT.RADIO); - mSkinListRadio.setText("Built-in:"); - mSkinListRadio.setToolTipText("Select an emulated screen size provided by the current Android target"); - mSkinListRadio.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - boolean listMode = mSkinListRadio.getSelection(); - enableSkinWidgets(listMode); - validatePage(); - } - }); - - mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN); - mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - mSkinCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - // get the skin info - loadSkin(); - } - }); - - mSkinSizeRadio = new Button(skinGroup, SWT.RADIO); - mSkinSizeRadio.setText("Resolution:"); - mSkinSizeRadio.setToolTipText("Select a custom emulated screen size"); - - mSkinSizeWidth = new Text(skinGroup, SWT.BORDER); - mSkinSizeWidth.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSkinSizeWidth.addVerifyListener(mDigitVerifier); - mSkinSizeWidth.addModifyListener(validateListener); - mSkinSizeWidth.setToolTipText("Width in pixels of the emulated screen size"); - - new Label(skinGroup, SWT.NONE).setText("x"); - - mSkinSizeHeight = new Text(skinGroup, SWT.BORDER); - mSkinSizeHeight.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSkinSizeHeight.addVerifyListener(mDigitVerifier); - mSkinSizeHeight.addModifyListener(validateListener); - mSkinSizeHeight.setToolTipText("Height in pixels of the emulated screen size"); - - mSkinListRadio.setSelection(true); - enableSkinWidgets(true); - - // --- hardware group - label = new Label(parent, SWT.NONE); - label.setText("Hardware:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group hwGroup = new Group(parent, SWT.NONE); - hwGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - hwGroup.setLayout(new GridLayout(2, false)); - - createHardwareTable(hwGroup); - - // composite for the side buttons - Composite hwButtons = new Composite(hwGroup, SWT.NONE); - hwButtons.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - hwButtons.setLayout(gl = new GridLayout(1, false)); - gl.marginHeight = gl.marginWidth = 0; - - Button b = new Button(hwButtons, SWT.PUSH | SWT.FLAT); - b.setText("New..."); - b.setToolTipText("Add a new hardware property"); - b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - b.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - HardwarePropertyChooser dialog = new HardwarePropertyChooser(parent.getShell(), - mHardwareMap, mProperties.keySet()); - if (dialog.open() == Window.OK) { - HardwareProperty choice = dialog.getProperty(); - if (choice != null) { - mProperties.put(choice.getName(), choice.getDefault()); - mHardwareViewer.refresh(); - } - } - } - }); - mDeleteHardwareProp = new Button(hwButtons, SWT.PUSH | SWT.FLAT); - mDeleteHardwareProp.setText("Delete"); - mDeleteHardwareProp.setToolTipText("Delete the selected hardware property"); - mDeleteHardwareProp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDeleteHardwareProp.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - ISelection selection = mHardwareViewer.getSelection(); - if (selection instanceof IStructuredSelection) { - String hwName = (String)((IStructuredSelection)selection).getFirstElement(); - mProperties.remove(hwName); - mHardwareViewer.refresh(); - } - } - }); - mDeleteHardwareProp.setEnabled(false); - - // --- end hardware group - - mForceCreation = new Button(parent, SWT.CHECK); - mForceCreation.setText("Override the existing AVD with the same name"); - mForceCreation.setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD."); - mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, - true, false, 2, 1)); - mForceCreation.setEnabled(false); - mForceCreation.addSelectionListener(validateListener); - - // add a separator to separate from the ok/cancel button - label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); - - // add stuff for the error display - mStatusComposite = new Composite(parent, SWT.NONE); - mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, - true, false, 3, 1)); - mStatusComposite.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - - mStatusIcon = new Label(mStatusComposite, SWT.NONE); - mStatusIcon.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - mStatusLabel = new Label(mStatusComposite, SWT.NONE); - mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mStatusLabel.setText(" \n "); //$NON-NLS-1$ - - reloadTargetCombo(); - } - - /** - * Creates the UI for the hardware properties table. - * This creates the {@link Table}, and several viewers ({@link TableViewer}, - * {@link TableViewerColumn}) and adds edit support for the 2nd column - */ - private void createHardwareTable(Composite parent) { - final Table hardwareTable = new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION); - GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); - gd.widthHint = 200; - gd.heightHint = 100; - hardwareTable.setLayoutData(gd); - hardwareTable.setHeaderVisible(true); - hardwareTable.setLinesVisible(true); - - // -- Table viewer - mHardwareViewer = new TableViewer(hardwareTable); - mHardwareViewer.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - // it's a single selection mode, we can just access the selection index - // from the table directly. - mDeleteHardwareProp.setEnabled(hardwareTable.getSelectionIndex() != -1); - } - }); - - // only a content provider. Use viewers per column below (for editing support) - mHardwareViewer.setContentProvider(new IStructuredContentProvider() { - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // we can just ignore this. we just use mProperties directly. - } - - @Override - public Object[] getElements(Object arg0) { - return mProperties.keySet().toArray(); - } - - @Override - public void dispose() { - // pass - } - }); - - // -- column 1: prop abstract name - TableColumn col1 = new TableColumn(hardwareTable, SWT.LEFT); - col1.setText("Property"); - col1.setWidth(150); - TableViewerColumn tvc1 = new TableViewerColumn(mHardwareViewer, col1); - tvc1.setLabelProvider(new CellLabelProvider() { - @Override - public void update(ViewerCell cell) { - String name = cell.getElement().toString(); - HardwareProperty prop = mHardwareMap.get(name); - if (prop != null) { - cell.setText(prop.getAbstract()); - } else { - cell.setText(String.format("%1$s (Unknown)", name)); - } - } - }); - - // -- column 2: prop value - TableColumn col2 = new TableColumn(hardwareTable, SWT.LEFT); - col2.setText("Value"); - col2.setWidth(50); - TableViewerColumn tvc2 = new TableViewerColumn(mHardwareViewer, col2); - tvc2.setLabelProvider(new CellLabelProvider() { - @Override - public void update(ViewerCell cell) { - String value = mProperties.get(cell.getElement()); - cell.setText(value != null ? value : ""); - } - }); - - // add editing support to the 2nd column - tvc2.setEditingSupport(new EditingSupport(mHardwareViewer) { - @Override - protected void setValue(Object element, Object value) { - String hardwareName = (String)element; - HardwareProperty property = mHardwareMap.get(hardwareName); - int index; - switch (property.getType()) { - case INTEGER: - mProperties.put((String)element, (String)value); - break; - case DISKSIZE: - if (HardwareProperties.DISKSIZE_PATTERN.matcher((String)value).matches()) { - mProperties.put((String)element, (String)value); - } - break; - case BOOLEAN: - index = (Integer)value; - mProperties.put((String)element, HardwareProperties.getBooleanValue(index)); - break; - case STRING_ENUM: - case INTEGER_ENUM: - // For a combo, value is the index of the enum to use. - index = (Integer)value; - String[] values = property.getEnum(); - if (values != null && values.length > index) { - mProperties.put((String)element, values[index]); - } - break; - } - mHardwareViewer.refresh(element); - } - - @Override - protected Object getValue(Object element) { - String hardwareName = (String)element; - HardwareProperty property = mHardwareMap.get(hardwareName); - String value = mProperties.get(hardwareName); - switch (property.getType()) { - case INTEGER: - // intended fall-through. - case DISKSIZE: - return value; - case BOOLEAN: - return HardwareProperties.getBooleanValueIndex(value); - case STRING_ENUM: - case INTEGER_ENUM: - // For a combo, we need to return the index of the value in the enum - String[] values = property.getEnum(); - if (values != null) { - for (int i = 0; i < values.length; i++) { - if (values[i].equals(value)) { - return i; - } - } - } - } - - return null; - } - - @Override - protected CellEditor getCellEditor(Object element) { - String hardwareName = (String)element; - HardwareProperty property = mHardwareMap.get(hardwareName); - switch (property.getType()) { - // TODO: custom TextCellEditor that restrict input. - case INTEGER: - // intended fall-through. - case DISKSIZE: - return new TextCellEditor(hardwareTable); - case BOOLEAN: - return new ComboBoxCellEditor(hardwareTable, - new String[] { - HardwareProperties.getBooleanValue(0), - HardwareProperties.getBooleanValue(1), - }, - SWT.READ_ONLY | SWT.DROP_DOWN); - case STRING_ENUM: - case INTEGER_ENUM: - String[] values = property.getEnum(); - if (values != null && values.length > 0) { - return new ComboBoxCellEditor(hardwareTable, - values, - SWT.READ_ONLY | SWT.DROP_DOWN); - } - } - return null; - } - - @Override - protected boolean canEdit(Object element) { - String hardwareName = (String)element; - HardwareProperty property = mHardwareMap.get(hardwareName); - return property != null; - } - }); - - - mHardwareViewer.setInput(mProperties); - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - /** - * When editing an existing AVD info, fill the UI that has just been created with - * the values from the AVD. - */ - public void fillExistingAvdInfo() { - if (mEditAvdInfo == null) { - return; - } - - mAvdName.setText(mEditAvdInfo.getName()); - - Map props = mEditAvdInfo.getProperties(); - - IAndroidTarget target = mEditAvdInfo.getTarget(); - if (target != null && !mCurrentTargets.isEmpty()) { - // Try to select the target in the target combo. - // This will fail if the AVD needs to be repaired. - // - // This is a linear search but the list is always - // small enough and we only do this once. - int n = mTargetCombo.getItemCount(); - for (int i = 0;i < n; i++) { - if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) { - mTargetCombo.select(i); - reloadTagAbiCombo(); - reloadSkinCombo(); - break; - } - } - } - - // select the abi type - ISystemImage[] systemImages = getSystemImages(target); - if (target != null && systemImages.length > 0) { - mTagAbiCombo.setEnabled(systemImages.length > 1); - String abiType = AvdInfo.getPrettyAbiType(mEditAvdInfo); - int n = mTagAbiCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (abiType.equals(mTagAbiCombo.getItem(i))) { - mTagAbiCombo.select(i); - reloadSkinCombo(); - break; - } - } - } - - if (props != null) { - - // First try the skin name and if it doesn't work fallback on the skin path - nextSkin: for (int s = 0; s < 2; s++) { - String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME - : AvdManager.AVD_INI_SKIN_PATH); - if (skin != null && skin.length() > 0) { - Matcher m = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin); - if (m.matches() && m.groupCount() == 2) { - enableSkinWidgets(false); - mSkinListRadio.setSelection(false); - mSkinSizeRadio.setSelection(true); - mSkinSizeWidth.setText(m.group(1)); - mSkinSizeHeight.setText(m.group(2)); - break nextSkin; - } else { - enableSkinWidgets(true); - mSkinSizeRadio.setSelection(false); - mSkinListRadio.setSelection(true); - - int n = mSkinCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (skin.equals(mSkinCombo.getItem(i))) { - mSkinCombo.select(i); - break nextSkin; - } - } - } - } - } - - String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH); - if (sdcard != null && sdcard.length() > 0) { - enableSdCardWidgets(false); - mSdCardSizeRadio.setSelection(false); - mSdCardFileRadio.setSelection(true); - mSdCardFile.setText(sdcard); - } - - sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE); - if (sdcard != null && sdcard.length() > 0) { - String[] values = new String[2]; - long sdcardSize = AvdManager.parseSdcardSize(sdcard, values); - - if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) { - enableSdCardWidgets(true); - mSdCardFileRadio.setSelection(false); - mSdCardSizeRadio.setSelection(true); - - mSdCardSize.setText(values[0]); - - String suffix = values[1]; - int n = mSdCardSizeCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) { - mSdCardSizeCombo.select(i); - } - } - } - } - - String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - if (snapshots != null && snapshots.length() > 0) { - mSnapshotCheck.setSelection(snapshots.equals("true")); - } - } - - mProperties.clear(); - - if (props != null) { - for (Entry entry : props.entrySet()) { - HardwareProperty prop = mHardwareMap.get(entry.getKey()); - if (prop != null && prop.isValidForUi()) { - mProperties.put(entry.getKey(), entry.getValue()); - } - } - } - - // Cleanup known non-hardware properties - mProperties.remove(AvdManager.AVD_INI_ABI_TYPE); - mProperties.remove(AvdManager.AVD_INI_CPU_ARCH); - mProperties.remove(AvdManager.AVD_INI_SKIN_PATH); - mProperties.remove(AvdManager.AVD_INI_SKIN_NAME); - mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE); - mProperties.remove(AvdManager.AVD_INI_SDCARD_PATH); - mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - mProperties.remove(AvdManager.AVD_INI_IMAGES_1); - mProperties.remove(AvdManager.AVD_INI_IMAGES_2); - - mHardwareViewer.refresh(); - } - - @Override - protected void okPressed() { - if (createAvd()) { - super.okPressed(); - } - } - - /** - * Enable or disable the sd card widgets. - * @param sizeMode if true the size-based widgets are to be enabled, and the file-based ones - * disabled. - */ - private void enableSdCardWidgets(boolean sizeMode) { - mSdCardSize.setEnabled(sizeMode); - mSdCardSizeCombo.setEnabled(sizeMode); - - mSdCardFile.setEnabled(!sizeMode); - mBrowseSdCard.setEnabled(!sizeMode); - } - - /** - * Enable or disable the skin widgets. - * @param listMode if true the list-based widgets are to be enabled, and the size-based ones - * disabled. - */ - private void enableSkinWidgets(boolean listMode) { - mSkinCombo.setEnabled(listMode); - - mSkinSizeWidth.setEnabled(!listMode); - mSkinSizeHeight.setEnabled(!listMode); - } - - - private void onBrowseSdCard() { - FileDialog dlg = new FileDialog(getContents().getShell(), SWT.OPEN); - dlg.setText("Choose SD Card image file."); - - String fileName = dlg.open(); - if (fileName != null) { - mSdCardFile.setText(fileName); - } - } - - - - private void reloadTargetCombo() { - String selected = null; - int index = mTargetCombo.getSelectionIndex(); - if (index >= 0) { - selected = mTargetCombo.getItem(index); - } - - mCurrentTargets.clear(); - mTargetCombo.removeAll(); - - boolean found = false; - index = -1; - - LocalSdk localSdk = mAvdManager.getLocalSdk(); - if (localSdk != null) { - for (IAndroidTarget target : localSdk.getTargets()) { - String name; - if (target.isPlatform()) { - name = String.format("%s - API Level %s", - target.getName(), - target.getVersion().getApiString()); - } else { - name = String.format("%s (%s) - API Level %s", - target.getName(), - target.getVendor(), - target.getVersion().getApiString()); - } - mCurrentTargets.put(name, target); - mTargetCombo.add(name); - if (!found) { - index++; - found = name.equals(selected); - } - } - } - - mTargetCombo.setEnabled(mCurrentTargets.size() > 0); - - if (found) { - mTargetCombo.select(index); - } - - reloadSkinCombo(); - } - - private void reloadSkinCombo() { - String selected = null; - int index = mSkinCombo.getSelectionIndex(); - if (index >= 0) { - selected = mSkinCombo.getItem(index); - } - - mSkinCombo.removeAll(); - mSkinCombo.setEnabled(false); - - index = mTargetCombo.getSelectionIndex(); - if (index >= 0) { - - String targetName = mTargetCombo.getItem(index); - - boolean found = false; - IAndroidTarget target = mCurrentTargets.get(targetName); - if (target != null) { - mSkinCombo.add(String.format("Default (%s)", target.getDefaultSkin())); - - index = -1; - for (File skin : target.getSkins()) { - mSkinCombo.add(skin.getName()); - if (!found) { - index++; - found = skin.equals(selected); - } - } - - mSkinCombo.setEnabled(true); - - if (found) { - mSkinCombo.select(index); - } else { - mSkinCombo.select(0); // default - loadSkin(); - } - } - } - } - - /** - * Reload all the abi types in the selection list - */ - private void reloadTagAbiCombo() { - String selected = null; - boolean found = false; - - int index = mTargetCombo.getSelectionIndex(); - if (index >= 0) { - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - - ISystemImage[] systemImages = getSystemImages(target); - - // keep a reference to the array into the combo app data field - // so that we can lookup the tag/abi later in getSelectedAbiType() - mTagAbiCombo.setData(ABI_SYS_IMG_DATA_KEY, systemImages); - - mTagAbiCombo.setEnabled(systemImages.length > 1); - - // If user explicitly selected an ABI before, preserve that option - // If user did not explicitly select before (only one option before) - // force them to select - index = mTagAbiCombo.getSelectionIndex(); - if (index >= 0 && mTagAbiCombo.getItemCount() > 1) { - selected = mTagAbiCombo.getItem(index); - } - - mTagAbiCombo.removeAll(); - - int i; - for ( i = 0; i < systemImages.length ; i++ ) { - String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i]); - mTagAbiCombo.add(prettyAbiType); - if (!found) { - found = prettyAbiType.equals(selected); - if (found) { - mTagAbiCombo.select(i); - } - } - } - - if (systemImages.length == 1) { - mTagAbiCombo.select(0); - } - } - } - - /** - * Validates the fields, displays errors and warnings. - * Enables the finish button if there are no errors. - */ - private void validatePage() { - String error = null; - String warning = null; - - // Validate AVD name - String avdName = mAvdName.getText().trim(); - boolean hasAvdName = avdName.length() > 0; - boolean isCreate = mEditAvdInfo == null || !avdName.equals(mEditAvdInfo.getName()); - - if (hasAvdName && !AvdManager.RE_AVD_NAME.matcher(avdName).matches()) { - error = String.format( - "AVD name '%1$s' contains invalid characters.\nAllowed characters are: %2$s", - avdName, AvdManager.CHARS_AVD_NAME); - } - - // Validate target - if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() < 0) { - error = "A target must be selected in order to create an AVD."; - } - - // validate abi type if the selected target supports multi archs. - if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() > 0) { - int index = mTargetCombo.getSelectionIndex(); - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - ISystemImage[] systemImages = getSystemImages(target); - if (systemImages.length > 1 && mTagAbiCombo.getSelectionIndex() < 0) { - error = "An ABI type must be selected in order to create an AVD."; - } - } - - // Validate SDCard path or value - if (error == null) { - // get the mode. We only need to check the file since the - // verifier on the size Text will prevent invalid input - boolean sdcardFileMode = mSdCardFileRadio.getSelection(); - if (sdcardFileMode) { - String sdName = mSdCardFile.getText().trim(); - if (sdName.length() > 0 && !new File(sdName).isFile()) { - error = "SD Card path isn't valid."; - } - } else { - String valueString = mSdCardSize.getText(); - if (valueString.length() > 0) { - long value = 0; - try { - value = Long.parseLong(valueString); - - int sizeIndex = mSdCardSizeCombo.getSelectionIndex(); - if (sizeIndex >= 0) { - // index 0 shifts by 10 (1024=K), index 1 by 20, etc. - value <<= 10*(1 + sizeIndex); - } - - if (value < AvdManager.SDCARD_MIN_BYTE_SIZE || - value > AvdManager.SDCARD_MAX_BYTE_SIZE) { - value = 0; - } - } catch (Exception e) { - // ignore, we'll test value below. - } - if (value <= 0) { - error = "SD Card size is invalid. Range is 9 MiB..1023 GiB."; - } else if (mEditAvdInfo != null) { - // When editing an existing AVD, compare with the existing - // sdcard size, if any. It only matters if there was an sdcard setting - // before. - Map props = mEditAvdInfo.getProperties(); - if (props != null) { - String original = - mEditAvdInfo.getProperties().get(AvdManager.AVD_INI_SDCARD_SIZE); - if (original != null && original.length() > 0) { - long originalSize = - AvdManager.parseSdcardSize(original, null/*parsedStrings*/); - if (originalSize > 0 && value != originalSize) { - warning = "A new SD Card file will be created.\nThe current SD Card file will be lost."; - } - } - } - } - } - } - } - - // validate the skin - if (error == null) { - // get the mode, we should only check if it's in size mode since - // the built-in list mode is always valid. - if (mSkinSizeRadio.getSelection()) { - // need both with and heigh to be non null - String width = mSkinSizeWidth.getText(); // no need for trim, since the verifier - String height = mSkinSizeHeight.getText(); // rejects non digit. - - if (width.length() == 0 || height.length() == 0) { - error = "Skin size is incorrect.\nBoth dimensions must be > 0."; - } - } - } - - // Check for duplicate AVD name - if (isCreate && hasAvdName && error == null && !mForceCreation.getSelection()) { - Pair conflict = mAvdManager.isAvdNameConflicting(avdName); - assert conflict != null; - switch(conflict.getFirst()) { - case NO_CONFLICT: - break; - case CONFLICT_EXISTING_AVD: - case CONFLICT_INVALID_AVD: - error = String.format( - "The AVD name '%s' is already used.\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - avdName); - break; - case CONFLICT_EXISTING_PATH: - error = String.format( - "Conflict with %s\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - conflict.getSecond()); - break; - default: - // Hmm not supposed to happen... probably someone expanded the - // enum without adding something here. In this case just do an - // assert and use a generic error message. - error = String.format( - "Conflict %s with %s.\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - conflict.getFirst().toString(), - conflict.getSecond()); - assert false; - break; - } - } - - if (error == null && mEditAvdInfo != null && isCreate) { - warning = String.format("The AVD '%1$s' will be duplicated into '%2$s'.", - mEditAvdInfo.getName(), - avdName); - } - - // Validate the create button - boolean can_create = hasAvdName && error == null; - if (can_create) { - can_create &= mTargetCombo.getSelectionIndex() >= 0; - } - mOkButton.setEnabled(can_create); - - // Adjust the create button label as needed - if (isCreate) { - mOkButton.setText("Create AVD"); - } else { - mOkButton.setText("Edit AVD"); - } - - // -- update UI - if (error != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(error); - } else if (warning != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(warning); - } else { - mStatusIcon.setImage(null); - mStatusLabel.setText(" \n "); //$NON-NLS-1$ - } - - mStatusComposite.pack(true); - } - - private void loadSkin() { - int targetIndex = mTargetCombo.getSelectionIndex(); - if (targetIndex < 0) { - return; - } - - // resolve the target. - String targetName = mTargetCombo.getItem(targetIndex); - IAndroidTarget target = mCurrentTargets.get(targetName); - if (target == null) { - return; - } - - // get the skin name - String skinName = null; - int skinIndex = mSkinCombo.getSelectionIndex(); - if (skinIndex < 0) { - return; - } else if (skinIndex == 0) { // default skin for the target - File skin = target.getDefaultSkin(); - if (skin != null) { - skinName = skin.getName(); - } - } else { - skinName = mSkinCombo.getItem(skinIndex); - } - - // load the skin properties - String path = target.getPath(IAndroidTarget.SKINS); - File skin = new File(path, skinName); - if (skin.isDirectory() == false && target.isPlatform() == false) { - // it's possible the skin is in the parent target - path = target.getParent().getPath(IAndroidTarget.SKINS); - skin = new File(path, skinName); - } - - if (skin.isDirectory() == false) { - return; - } - - // now get the hardware.ini from the add-on (if applicable) and from the skin - // (if applicable) - HashMap hardwareValues = new HashMap(); - if (target.isPlatform() == false) { - FileWrapper targetHardwareFile = new FileWrapper(target.getLocation(), - AvdManager.HARDWARE_INI); - if (targetHardwareFile.isFile()) { - Map targetHardwareConfig = ProjectProperties.parsePropertyFile( - targetHardwareFile, null /*log*/); - - if (targetHardwareConfig != null) { - hardwareValues.putAll(targetHardwareConfig); - } - } - } - - // from the skin - FileWrapper skinHardwareFile = new FileWrapper(skin, AvdManager.HARDWARE_INI); - if (skinHardwareFile.isFile()) { - Map skinHardwareConfig = ProjectProperties.parsePropertyFile( - skinHardwareFile, null /*log*/); - - if (skinHardwareConfig != null) { - hardwareValues.putAll(skinHardwareConfig); - } - } - - // now set those values in the list of properties for the AVD. - // We just check that none of those properties have been edited by the user yet. - for (Entry entry : hardwareValues.entrySet()) { - if (mEditedProperties.contains(entry.getKey()) == false) { - mProperties.put(entry.getKey(), entry.getValue()); - } - } - - mHardwareViewer.refresh(); - } - - /** - * Creates an AVD from the values in the UI. Called when the user presses the OK button. - */ - private boolean createAvd() { - String avdName = mAvdName.getText().trim(); - int index = mTargetCombo.getSelectionIndex(); - - // quick check on the name and the target selection - if (avdName.length() == 0 || index < 0) { - return false; - } - - // resolve the target. - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - if (target == null) { - return false; - } - - // get the tag & abi type - IdDisplay tag = SystemImage.DEFAULT_TAG; - mAbiType = SdkConstants.ABI_ARMEABI; - Object appData = mTagAbiCombo.getData(ABI_SYS_IMG_DATA_KEY); - if (appData instanceof ISystemImage[]) { - int abiIndex = mTagAbiCombo.getSelectionIndex(); - ISystemImage[] systemImages = (ISystemImage[]) appData; - if (abiIndex >= 0 && abiIndex < systemImages.length) { - ISystemImage systemImage = systemImages[abiIndex]; - tag = systemImage.getTag(); - mAbiType = systemImage.getAbiType(); - } - } - - // get the SD card data from the UI. - String sdName = null; - if (mSdCardSizeRadio.getSelection()) { - // size mode - String value = mSdCardSize.getText().trim(); - if (value.length() > 0) { - sdName = value; - // add the unit - switch (mSdCardSizeCombo.getSelectionIndex()) { - case 0: - sdName += "K"; //$NON-NLS-1$ - break; - case 1: - sdName += "M"; //$NON-NLS-1$ - break; - case 2: - sdName += "G"; //$NON-NLS-1$ - break; - default: - // shouldn't be here - assert false; - } - } - } else { - // file mode. - sdName = mSdCardFile.getText().trim(); - } - - // get the Skin data from the UI - String skinName = null; - if (mSkinListRadio.getSelection()) { - // built-in list provides the skin - int skinIndex = mSkinCombo.getSelectionIndex(); - if (skinIndex > 0) { - // index 0 is the default, we don't use it - skinName = mSkinCombo.getItem(skinIndex); - } - } else { - // size mode. get both size and writes it as a skin name - // thanks to validatePage() we know the content of the fields is correct - skinName = mSkinSizeWidth.getText() + "x" + mSkinSizeHeight.getText(); //$NON-NLS-1$ - } - - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog( - String.format("Result of creating AVD '%s':", avdName), - getContents().getDisplay(), - false /*logErrorsOnly*/); - } - - File avdFolder = null; - try { - avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName); - } catch (AndroidLocationException e) { - return false; - } - - boolean force = mForceCreation.getSelection(); - boolean snapshot = mSnapshotCheck.getSelection(); - - boolean success = false; - AvdInfo avdInfo = mAvdManager.createAvd( - avdFolder, - avdName, - target, - tag, - mAbiType, - null, //skinFolder - skinName, - sdName, - mProperties, - null, // bootProps - snapshot, - force, - mEditAvdInfo != null, //edit existing - log); - - success = avdInfo != null; - - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(success); - } - return success; - } - - /** - * Returns the list of system images of a target. - *

- * If target is null, returns an empty list. - * If target is an add-on with no system images, return the list from its parent platform. - * - * @param target An IAndroidTarget. Can be null. - * @return A non-null ISystemImage array. Can be empty. - */ - private ISystemImage[] getSystemImages(IAndroidTarget target) { - if (target != null) { - ISystemImage[] images = target.getSystemImages(); - - if ((images == null || images.length == 0) && !target.isPlatform()) { - // If an add-on does not provide any system images, use the ones from the parent. - images = target.getParent().getSystemImages(); - } - - if (images != null) { - return images; - } - } - - return new ISystemImage[0]; - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/AvdManagerWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/AvdManagerWindow.java index 01972988..30af250d 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/AvdManagerWindow.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/AvdManagerWindow.java @@ -17,9 +17,9 @@ package com.android.sdkuilib.repository; import com.android.sdkuilib.internal.repository.ui.AvdManagerWindowImpl1; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.utils.ILogger; +import org.eclipse.andmore.sdktool.SdkCallAgent; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.widgets.Shell; /** @@ -70,20 +70,34 @@ public enum AvdInvocationContext { * Creates a new window. Caller must call open(), which will block. * * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. + * @param sdkCallAgent Mediates between application and UI layer * @param context The {@link AvdInvocationContext} to change the behavior depending on who's * opening the SDK Manager. */ public AvdManagerWindow( Shell parentShell, - ILogger sdkLog, - String osSdkRoot, + SdkCallAgent sdkCallAgent, + AvdInvocationContext context) { + this(parentShell, + sdkCallAgent.getSdkContext(), + context); + } + + /** + * Creates a new window. Caller must call open(), which will block. + * + * @param parentShell Parent shell. + * @param sdkContext SDK handler and repo manager + * @param context The {@link AvdInvocationContext} to change the behavior depending on who's + * opening the SDK Manager. + */ + public AvdManagerWindow( + Shell parentShell, + SdkContext sdkContext, AvdInvocationContext context) { mWindow = new AvdManagerWindowImpl1( parentShell, - sdkLog, - osSdkRoot, + sdkContext, context); } diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/ISdkChangeListener.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/ISdkChangeListener.java similarity index 95% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/ISdkChangeListener.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/ISdkChangeListener.java index 5c0cab86..9cca7aa8 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/repository/ISdkChangeListener.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/ISdkChangeListener.java @@ -1,54 +1,54 @@ -/* - * Copyright (C) 2010 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.repository; - - -/** - * Interface for listeners on SDK modifications by the SDK Manager UI. - * This notifies when the SDK manager is first loading the SDK or before/after it installed - * a package. - */ -public interface ISdkChangeListener { - /** - * Invoked when the content of the SDK is being loaded by the SDK Manager UI - * for the first time. - * This is generally followed by a call to {@link #onSdkReload()} - * or by a call to {@link #preInstallHook()}. - */ - void onSdkLoaded(); - - /** - * Invoked when the SDK Manager UI is about to start installing packages. - * This will be followed by a call to {@link #postInstallHook()}. - */ - void preInstallHook(); - - /** - * Invoked when the SDK Manager UI is done installing packages. - * Some new packages might have been installed or the user might have cancelled the operation. - * This is generally followed by a call to {@link #onSdkReload()}. - */ - void postInstallHook(); - - /** - * Invoked when the content of the SDK is being reloaded by the SDK Manager UI, - * typically after a package was installed. The SDK content might or might not - * have changed. - */ - void onSdkReload(); -} - +/* + * Copyright (C) 2010 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.sdkuilib.repository; + + +/** + * Interface for listeners on SDK modifications by the SDK Manager UI. + * This notifies when the SDK manager is first loading the SDK or before/after it installed + * a package. + */ +public interface ISdkChangeListener { + /** + * Invoked when the content of the SDK is being loaded by the SDK Manager UI + * for the first time. + * This is generally followed by a call to {@link #onSdkReload()} + * or by a call to {@link #preInstallHook()}. + */ + void onSdkLoaded(); + + /** + * Invoked when the SDK Manager UI is about to start installing packages. + * This will be followed by a call to {@link #postInstallHook()}. + */ + void preInstallHook(); + + /** + * Invoked when the SDK Manager UI is done installing packages. + * Some new packages might have been installed or the user might have cancelled the operation. + * This is generally followed by a call to {@link #onSdkReload()}. + */ + void postInstallHook(); + + /** + * Invoked when the content of the SDK is being reloaded by the SDK Manager UI, + * typically after a package was installed. The SDK content might or might not + * have changed. + */ + void onSdkReload(); +} + diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/SdkUpdaterWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/SdkUpdaterWindow.java index b91f03c6..960eec46 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/SdkUpdaterWindow.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/repository/SdkUpdaterWindow.java @@ -16,10 +16,13 @@ package com.android.sdkuilib.repository; -import com.android.sdklib.repository.ISdkChangeListener; +import com.android.repository.api.RepoManager; +import com.android.sdklib.repository.AndroidSdkHandler; import com.android.sdkuilib.internal.repository.ISdkUpdaterWindow; import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; -import com.android.utils.ILogger; + +import org.eclipse.andmore.sdktool.SdkCallAgent; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.widgets.Shell; @@ -74,18 +77,32 @@ public enum SdkInvocationContext { * Creates a new window. Caller must call open(), which will block. * * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. + * @param sdkCallAgent Mediates between application and UI layer + * @param context The {@link SdkInvocationContext} to change the behavior depending on who's + * opening the SDK Manager. + */ + public SdkUpdaterWindow( + Shell parentShell, + SdkCallAgent sdkCallAgent, + SdkInvocationContext context) { + + this(parentShell, sdkCallAgent.getSdkContext(), context); + } + + /** + * Creates a new window. Caller must call open(), which will block. + * + * @param parentShell Parent shell. + * @param sdkContext SDK handler and repo manager * @param context The {@link SdkInvocationContext} to change the behavior depending on who's * opening the SDK Manager. */ public SdkUpdaterWindow( Shell parentShell, - ILogger sdkLog, - String osSdkRoot, + SdkContext sdkContext, SdkInvocationContext context) { - mWindow = new SdkUpdaterWindowImpl2(parentShell, sdkLog, osSdkRoot, context); + mWindow = new SdkUpdaterWindowImpl2(parentShell, sdkContext, context); } /** diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AdtUpdateDialog.java similarity index 52% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AdtUpdateDialog.java index 5fcd1f77..76ce1b63 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AdtUpdateDialog.java @@ -14,29 +14,32 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.repository.ui; - +package com.android.sdkuilib.ui; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoPackage; +import com.android.repository.api.UpdatablePackage; +import com.android.repository.impl.meta.TypeDetails; import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.updater.PackageLoader; -import com.android.sdklib.internal.repository.updater.SettingsController; -import com.android.sdklib.internal.repository.updater.PackageLoader.IAutoInstallTask; -import com.android.sdkuilib.internal.repository.SwtUpdaterData; -import com.android.sdkuilib.internal.repository.core.SdkLogAdapter; +import com.android.sdklib.repository.meta.DetailsTypes.ExtraDetailsType; +import com.android.sdklib.repository.meta.DetailsTypes.PlatformDetailsType; +import com.android.sdkuilib.internal.repository.PackageManager.RemotePackageHandler; +import com.android.sdkuilib.internal.repository.PackageManager.UpdatablePackageHandler; +import com.android.sdkuilib.internal.repository.Settings; +import com.android.sdkuilib.internal.repository.content.PackageType; +import com.android.sdkuilib.internal.repository.content.PkgItem; +import com.android.sdkuilib.internal.repository.ui.LogWindow; +import com.android.sdkuilib.internal.repository.ui.SdkProgressFactory; import com.android.sdkuilib.internal.tasks.ProgressView; -import com.android.sdkuilib.internal.tasks.ProgressViewFactory; +import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; import com.android.sdkuilib.ui.GridDataBuilder; import com.android.sdkuilib.ui.GridLayoutBuilder; import com.android.sdkuilib.ui.SwtBaseDialog; import com.android.utils.ILogger; import com.android.utils.Pair; +import org.eclipse.andmore.sdktool.SdkCallAgent; +import org.eclipse.andmore.sdktool.SdkContext; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridLayout; @@ -46,11 +49,13 @@ import org.eclipse.swt.widgets.Shell; import java.io.File; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** + * TODO - Integrate this class with SdkUpdaterWindow * This is a private implementation of UpdateWindow for ADT, * designed to install a very specific package. *

@@ -72,16 +77,15 @@ public class AdtUpdateDialog extends SwtBaseDialog { public static final int USE_MAX_REMOTE_API_LEVEL = 0; private static final String APP_NAME = "Android SDK Manager"; - private final SwtUpdaterData mUpdaterData; + private final SdkContext mSdkContext; private Boolean mResultCode = Boolean.FALSE; - private Map mResultPaths = null; - private SettingsController mSettingsController; + private Map mResultPaths = null; private PackageFilter mPackageFilter; - private PackageLoader mPackageLoader; private ProgressBar mProgressBar; private Label mStatusText; + private LogWindow mLogWindow; /** * Creates a new {@link AdtUpdateDialog}. @@ -89,39 +93,37 @@ public class AdtUpdateDialog extends SwtBaseDialog { * {@link #installPlatformPackage} after this. * * @param parentShell The existing parent shell. Must not be null. - * @param sdkLog An SDK logger. Must not be null. - * @param osSdkRoot The current SDK root OS path. Must not be null or empty. - */ + * @param sdkCallAgent Mediator between application and UI layer + */ public AdtUpdateDialog( Shell parentShell, - ILogger sdkLog, - String osSdkRoot) { + SdkCallAgent sdkCallAgent) { super(parentShell, SWT.NONE, APP_NAME); - mUpdaterData = new SwtUpdaterData(osSdkRoot, sdkLog); + mSdkContext = sdkCallAgent.getSdkContext(); } /** - * Displays the update dialog and triggers installation of the requested {@code extra} - * package with the specified vendor and path attributes. + * Displays the update dialog and triggers installation of the requested platform + * package with the specified API level. *

* Callers must not try to reuse this dialog after this call. * - * @param vendor The extra package vendor string to match. - * @param path The extra package path string to match. + * @param apiLevel The platform API level to match. + * The special value {@link #USE_MAX_REMOTE_API_LEVEL} means to use + * the highest API level available on the remote repository. * @return A boolean indicating whether the installation was successful (meaning the package * was either already present, or got installed or updated properly) and a {@link File} * with the path to the root folder of the package. The file is null when the boolean * is false, otherwise it should point to an existing valid folder. - * @wbp.parser.entryPoint */ - public Pair installExtraPackage(String vendor, String path) { - mPackageFilter = createExtraFilter(vendor, path); + public Pair installPlatformPackage(int apiLevel) { + mPackageFilter = createPlatformFilter(apiLevel); open(); File installPath = null; if (mResultPaths != null) { - for (Entry entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof ExtraPackage) { + for (Entry entry : mResultPaths.entrySet()) { + if (entry.getKey().getMetaPackage().getPackageType() == PackageType.platforms) { installPath = entry.getValue(); break; } @@ -132,55 +134,54 @@ public Pair installExtraPackage(String vendor, String path) { } /** - * Displays the update dialog and triggers installation of platform-tools package. + * Displays the update dialog and triggers installation of the requested {@code extra} + * package with the specified vendor and path attributes. *

* Callers must not try to reuse this dialog after this call. * + * @param vendor The extra package vendor string to match. + * @param path The extra package path string to match. * @return A boolean indicating whether the installation was successful (meaning the package * was either already present, or got installed or updated properly) and a {@link File} * with the path to the root folder of the package. The file is null when the boolean * is false, otherwise it should point to an existing valid folder. * @wbp.parser.entryPoint */ - public Pair installPlatformTools() { - mPackageFilter = createPlatformToolsFilter(); + public Pair installExtraPackage(String vendor, String path) { + mPackageFilter = createExtraFilter(vendor, path); open(); File installPath = null; if (mResultPaths != null) { - for (Entry entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof ExtraPackage) { + for (Entry entry : mResultPaths.entrySet()) { + if (entry.getKey().getMetaPackage().getPackageType() == PackageType.extras) { installPath = entry.getValue(); break; } } } - return Pair.of(mResultCode, installPath); } /** - * Displays the update dialog and triggers installation of the requested platform - * package with the specified API level. + * Displays the update dialog and triggers installation of platform-tools package. *

* Callers must not try to reuse this dialog after this call. * - * @param apiLevel The platform API level to match. - * The special value {@link #USE_MAX_REMOTE_API_LEVEL} means to use - * the highest API level available on the remote repository. * @return A boolean indicating whether the installation was successful (meaning the package * was either already present, or got installed or updated properly) and a {@link File} * with the path to the root folder of the package. The file is null when the boolean * is false, otherwise it should point to an existing valid folder. + * @wbp.parser.entryPoint */ - public Pair installPlatformPackage(int apiLevel) { - mPackageFilter = createPlatformFilter(apiLevel); + public Pair installPlatformTools() { + mPackageFilter = createPlatformToolsFilter(); open(); File installPath = null; if (mResultPaths != null) { - for (Entry entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof PlatformPackage) { + for (Entry entry : mResultPaths.entrySet()) { + if (entry.getKey().getMetaPackage().getPackageType() == PackageType.platform_tools) { installPath = entry.getValue(); break; } @@ -214,11 +215,7 @@ protected void createContents() { Shell shell = getShell(); shell.setMinimumSize(new Point(450, 100)); shell.setSize(450, 100); - - mUpdaterData.setWindowShell(shell); - GridLayoutBuilder.create(shell).columns(1); - Composite composite1 = new Composite(shell, SWT.NONE); composite1.setLayout(new GridLayout(1, false)); GridDataBuilder.create(composite1).fill().grab(); @@ -229,64 +226,101 @@ protected void createContents() { mStatusText = new Label(composite1, SWT.NONE); mStatusText.setText("Status Placeholder"); //$NON-NLS-1$ placeholder GridDataBuilder.create(mStatusText).hFill().hGrab(); + createLogWindow(); } + /** + * Creates the log window. + *

+ * If this is invoked from an IDE, we also define a secondary logger so that all + * messages flow to the IDE log. This may or may not be what we want in the end + * (e.g. a middle ground would be to repeat error, and ignore normal/verbose) + */ + private void createLogWindow() { + mLogWindow = new LogWindow(getShell(), mSdkContext.getSdkLog()); + mLogWindow.open(); + } + + @Override protected void postCreate() { - ProgressViewFactory factory = new ProgressViewFactory(); - factory.setProgressView(new ProgressView( - mStatusText, - mProgressBar, - null /*buttonStop*/, - new SdkLogAdapter(mUpdaterData.getSdkLog()))); - mUpdaterData.setTaskFactory(factory); - - setupSources(); - initializeSettings(); + // This class delegates all logging to the mLogWindow window + // and filters errors to make sure the window is visible when + // an error is logged. + SdkProgressFactory.ISdkLogWindow logAdapter = new SdkProgressFactory.ISdkLogWindow() { + @Override + public void setDescription(String description) { + mLogWindow.setDescription(description); + } + + @Override + public void log(String log) { + mLogWindow.log(log); + } - if (mUpdaterData.checkIfInitFailed()) { + @Override + public void logVerbose(String log) { + mLogWindow.logVerbose(log); + } + + @Override + public void logError(String log) { + mLogWindow.logError(log); + } + @Override + public void show() + { + // Run the window visibility check/toggle on the UI thread. + // Note: at least on Windows, it seems ok to check for the window visibility + // on a sub-thread but that doesn't seem cross-platform safe. We shouldn't + // have a lot of error logging, so this should be acceptable. If not, we could + // cache the visibility state. + if (getShell() != null && !getShell().isDisposed()) { + getShell().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + if (!mLogWindow.isVisible()) { + mLogWindow.setVisible(true); + } + } + }); + } + } + }; + SdkProgressFactory factory = new SdkProgressFactory(mStatusText, mProgressBar, null, logAdapter); + initializeSettings(); + if (mSdkContext.hasError()) + { + ILogger logger = (ILogger)factory; + Iterator iterator = mSdkContext.getLogMessages().iterator(); + while(iterator.hasNext()) + logger.error(null, iterator.next()); close(); return; } - - mUpdaterData.broadcastOnSdkLoaded(); - - mPackageLoader = new PackageLoader(mUpdaterData); + mSdkContext.setSdkLogger(factory); + mSdkContext.setSdkProgressIndicator(factory); } @Override protected void eventLoop() { - mPackageLoader.loadPackagesWithInstallTask( - mPackageFilter.installFlags(), - new IAutoInstallTask() { - @Override - public Package[] filterLoadedSource(SdkSource source, Package[] packages) { - for (Package pkg : packages) { - mPackageFilter.visit(pkg); - } - return packages; - } - - @Override - public boolean acceptPackage(Package pkg) { + /* + public boolean acceptPackage(PkgItem pkg) { // Is this the package we want to install? return mPackageFilter.accept(pkg); } - @Override - public void setResult(boolean success, Map installPaths) { + public void setResult(boolean success, Map installPaths) { // Capture the result from the installation. mResultCode = Boolean.valueOf(success); mResultPaths = installPaths; } - @Override - public void taskCompleted() { + public void taskCompleted() { // We can close that window now. close(); } - }); - +*/ super.eventLoop(); } @@ -299,22 +333,23 @@ public void taskCompleted() { // --- Internals & UI Callbacks ----------- - /** - * Used to initialize the sources. - */ - private void setupSources() { - mUpdaterData.setupDefaultSources(); - } - /** * Initializes settings. + * This must be called after addExtraPages(), which created a settings page. + * Iterate through all the pages to find the first (and supposedly unique) setting page, + * and use it to load and apply these settings. */ - private void initializeSettings() { - mSettingsController = mUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); + private boolean initializeSettings() { + Settings settings = new Settings(); + if (settings.initialize(mSdkContext.getSdkLog())) + { + mSdkContext.setSettings(settings); + return true; + } + return false; } + // ---- private static abstract class PackageFilter { @@ -322,10 +357,10 @@ private static abstract class PackageFilter { abstract int installFlags(); /** Visit a new package definition, in case we need to adjust the filter dynamically. */ - abstract void visit(Package pkg); + abstract void visit(PkgItem pkg); /** Checks whether this is the package we've been looking for. */ - abstract boolean accept(Package pkg); + abstract boolean accept(PkgItem pkg); } public static PackageFilter createExtraFilter( @@ -336,33 +371,30 @@ public static PackageFilter createExtraFilter( String mPath = path; @Override - boolean accept(Package pkg) { - if (pkg instanceof ExtraPackage) { - ExtraPackage ep = (ExtraPackage) pkg; - if (ep.getVendorId().equals(mVendor)) { - // Check actual extra field first - if (ep.getPath().equals(mPath)) { - return true; - } - // If not, check whether this is one of the values. - for (String oldPath : ep.getOldPaths()) { - if (oldPath.equals(mPath)) { - return true; - } - } + boolean accept(PkgItem pkg) { + if (pkg.getMetaPackage().getPackageType() == PackageType.extras) { + TypeDetails details = pkg.getMainPackage().getTypeDetails(); + if (details instanceof ExtraDetailsType) { + ExtraDetailsType extraDetailsType = (ExtraDetailsType)details; + if (extraDetailsType.getVendor().getId().equals(mVendor)) { + // Check actual extra field + if (pkg.getMainPackage().getPath().equals(mPath)) { + return true; + } + } } - } + } return false; } @Override - void visit(Package pkg) { + void visit(PkgItem pkg) { // nop } @Override int installFlags() { - return SwtUpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; + return SdkCallAgent.TOOLS_MSG_UPDATED_FROM_ADT; } }; } @@ -370,18 +402,18 @@ int installFlags() { private PackageFilter createPlatformToolsFilter() { return new PackageFilter() { @Override - boolean accept(Package pkg) { - return pkg instanceof PlatformToolPackage; + boolean accept(PkgItem pkg) { + return pkg.getMetaPackage().getPackageType() == PackageType.platform_tools; } @Override - void visit(Package pkg) { + void visit(PkgItem pkg) { // nop } @Override int installFlags() { - return SwtUpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; + return SdkCallAgent.TOOLS_MSG_UPDATED_FROM_ADT; } }; } @@ -392,35 +424,41 @@ public static PackageFilter createPlatformFilter(final int apiLevel) { boolean mFindMaxApi = apiLevel == USE_MAX_REMOTE_API_LEVEL; @Override - boolean accept(Package pkg) { - if (pkg instanceof PlatformPackage) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - return !v.isPreview() && v.getApiLevel() == mApiLevel; + boolean accept(PkgItem pkg) { + if (pkg.getMetaPackage().getPackageType() == PackageType.platforms) { + RepoPackage remotePackage = pkg.getMainPackage(); + TypeDetails details = remotePackage.getTypeDetails(); + if (details instanceof PlatformDetailsType) { + PlatformDetailsType platformDetailsType = (PlatformDetailsType)details; + AndroidVersion androidVersion = platformDetailsType.getAndroidVersion(); + return !androidVersion.isPreview() && androidVersion.getApiLevel() == mApiLevel; + } } return false; } @Override - void visit(Package pkg) { + void visit(PkgItem pkg) { // Try to find the max API in all remote packages - if (mFindMaxApi && - pkg instanceof PlatformPackage && - !pkg.isLocal()) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int api = v.getApiLevel(); - if (api > mApiLevel) { - mApiLevel = api; - } + if (mFindMaxApi && (pkg.getMetaPackage().getPackageType() == PackageType.platforms)) { + RepoPackage remotePackage = pkg.getMainPackage(); + TypeDetails details = remotePackage.getTypeDetails(); + if ((details instanceof PlatformDetailsType) && (remotePackage instanceof RemotePackage)) { + PlatformDetailsType platformDetailsType = (PlatformDetailsType)details; + AndroidVersion androidVersion = platformDetailsType.getAndroidVersion(); + if (!androidVersion.isPreview()) { + int api = androidVersion.getApiLevel(); + if (api > mApiLevel) { + mApiLevel = api; + } + } } } } @Override int installFlags() { - return SwtUpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; + return SdkCallAgent.TOOLS_MSG_UPDATED_FROM_ADT; } }; } @@ -433,24 +471,26 @@ public static PackageFilter createNewSdkFilter(final Set apiLevels) { boolean mNeedPlatformTools = true; @Override - boolean accept(Package pkg) { - if (!pkg.isLocal()) { - if (pkg instanceof PlatformPackage) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int level = v.getApiLevel(); - if ((mFindMaxApi && level == mMaxApiLevel) || - (level > 0 && apiLevels.contains(level))) { - return true; - } - } - } else if (mNeedTools && pkg instanceof ToolPackage) { + boolean accept(PkgItem pkg) { + RepoPackage repoPackage = pkg.getMainPackage(); + if (repoPackage instanceof RemotePackage) { + TypeDetails details = repoPackage.getTypeDetails(); + if ((details instanceof PlatformDetailsType)) { + PlatformDetailsType platformDetailsType = (PlatformDetailsType)details; + AndroidVersion androidVersion = platformDetailsType.getAndroidVersion(); + if (!androidVersion.isPreview()) { + int level = androidVersion.getApiLevel(); + if ((mFindMaxApi && level == mMaxApiLevel) || + (level > 0 && apiLevels.contains(level))) { + return true; + } + } + } else if (mNeedTools && (pkg.getMetaPackage().getPackageType() == PackageType.tools)) { // We want a tool package. There should be only one, // but in case of error just take the first one. mNeedTools = false; return true; - } else if (mNeedPlatformTools && pkg instanceof PlatformToolPackage) { + } else if (mNeedPlatformTools && (pkg.getMetaPackage().getPackageType() == PackageType.platform_tools)) { // We want a platform-tool package. There should be only one, // but in case of error just take the first one. mNeedPlatformTools = false; @@ -461,31 +501,31 @@ boolean accept(Package pkg) { } @Override - void visit(Package pkg) { + void visit(PkgItem pkg) { // Try to find the max API in all remote packages - if (mFindMaxApi && - pkg instanceof PlatformPackage && - !pkg.isLocal()) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int api = v.getApiLevel(); - if (api > mMaxApiLevel) { - mMaxApiLevel = api; - } + if (mFindMaxApi && (pkg.getMetaPackage().getPackageType() == PackageType.platforms)) { + RepoPackage remotePackage = pkg.getMainPackage(); + TypeDetails details = remotePackage.getTypeDetails(); + if ((details instanceof PlatformDetailsType) && (remotePackage instanceof RemotePackage)) { + PlatformDetailsType platformDetailsType = (PlatformDetailsType)details; + AndroidVersion androidVersion = platformDetailsType.getAndroidVersion(); + if (!androidVersion.isPreview()) { + int api = androidVersion.getApiLevel(); + if (api > mMaxApiLevel) { + mMaxApiLevel = api; + } + } } } } @Override int installFlags() { - return SwtUpdaterData.NO_TOOLS_MSG; + return SdkCallAgent.NO_TOOLS_MSG; } }; } - - // End of hiding from SWT Designer //$hide<<$ diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdDisplayMode.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdDisplayMode.java new file mode 100644 index 00000000..573154ca --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdDisplayMode.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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.sdkuilib.ui; + +import com.android.sdkuilib.internal.widgets.AvdSelector; + +/** + * The display mode of the AVD Selector. + */ +public enum AvdDisplayMode { + /** + * Manager mode. Invalid AVDs are displayed. Buttons to create/delete AVDs + */ + MANAGER, + + /** + * Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but + * there is a button to open the AVD Manager. + * In the "check" selection mode, checkboxes are displayed on each line + * and {@link AvdSelector#getSelected()} returns the line that is checked + * even if it is not the currently selected line. Only one line can + * be checked at once. + */ + SIMPLE_CHECK, + + /** + * Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but + * there is a button to open the AVD Manager. + * In the "select" selection mode, there are no checkboxes and + * {@link AvdSelector#getSelected()} returns the line currently selected. + * Only one line can be selected at once. + */ + SIMPLE_SELECTION, + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdSelectorWindow.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdSelectorWindow.java new file mode 100644 index 00000000..dee8cdb7 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/AvdSelectorWindow.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2017 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.sdkuilib.ui; + +import org.eclipse.andmore.sdktool.SdkCallAgent; +import org.eclipse.andmore.sdktool.SdkContext; +import org.eclipse.andmore.sdktool.Utilities; +import org.eclipse.andmore.sdktool.Utilities.Compatibility; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TableItem; + +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; +import com.android.sdkuilib.internal.widgets.AvdSelector; +import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter; + +/** + * A control to select an Android Virtual Device (AVD) + * @author Andrew Bowley + * + */ +public class AvdSelectorWindow { + + private final AvdSelector avdSelector; + private final SdkContext sdkContext; + private final SdkTargets sdkTargets; + + public AvdSelectorWindow(Composite parent, SdkCallAgent sdkCallAgent) { + this.sdkContext = sdkCallAgent.getSdkContext(); + sdkTargets = new SdkTargets(sdkContext); + avdSelector = new AvdSelector(parent, sdkContext, (IAvdFilter)null, AvdDisplayMode.SIMPLE_CHECK); + } + + /** + * Sets the current target selection. + *

+ * If the selection is actually changed, this will invoke the selection listener + * (if any) with a null event. + * + * @param target the target to be selected. Use null to deselect everything. + * @return true if the target could be selected, false otherwise. + */ + public void setSelection(AvdInfo avd) { + avdSelector.setSelection(avd); + } + + /** + * Returns the currently selected item. In {@link DisplayMode#SIMPLE_CHECK} mode this will + * return the {@link AvdInfo} that is checked instead of the list selection. + * + * @return The currently selected item or null. + */ + public AvdInfo getSelected() { + AvdAgent avdAgent = avdSelector.getSelected(); + return avdAgent != null ? avdAgent.getAvd() : null; + } + + /** + * Sets the table grid layout data. + * + * @param heightHint If > 0, the height hint is set to the requested value. + */ + public void setTableHeightHint(int heightHint) { + avdSelector.setTableHeightHint(heightHint); + } + + /** + * Sets a selection listener. Set it to null to remove it. + * The listener will be called after this table processed its selection + * events so that the caller can see the updated state. + *

+ * The event's item contains a {@link TableItem}. + * The {@link TableItem#getData()} contains an {@link IAndroidTarget}. + *

+ * It is recommended that the caller uses the {@link #getSelected()} method instead. + *

+ * The default behavior for double click (when not in {@link DisplayMode#SIMPLE_CHECK}) is to + * display the details of the selected AVD.
+ * To disable it (when you provide your own double click action), set + * {@link SelectionEvent#doit} to false in + * {@link SelectionListener#widgetDefaultSelected(SelectionEvent)} + * + * @param selectionListener The new listener or null to remove it. + */ + public void setSelectionListener(SelectionListener selectionListener) { + avdSelector.setSelectionListener(selectionListener); + } + + /** + * Enables the receiver if the argument is true, and disables it otherwise. + * A disabled control is typically not selectable from the user interface + * and draws with an inactive or "grayed" look. + * + * @param enabled the new enabled state. + */ + public void setEnabled(boolean enabled) { + avdSelector.setEnabled(enabled); + } + + /** + * Sets a new AVD manager and updates AVD filter parameters + * This also refreshes the display + * @param manager the AVD manager. + */ + public void setManager(AvdManager manager, IAndroidTarget target, AndroidVersion minApiVersion) { + avdSelector.setManager(manager); + avdSelector.refresh(false); + avdSelector.setFilter(getCompatibilityFilter(target, minApiVersion)); + } + + private IAvdFilter getCompatibilityFilter(IAndroidTarget target, AndroidVersion minApiVersion) { + return new IAvdFilter() { + + @Override + public void prepare() { + } + + @Override + public void cleanup() { + } + + @Override + public boolean accept(AvdAgent avdAgent) { + AvdInfo info = avdAgent.getAvd(); + Compatibility c = + Utilities.canRun(info, getAndroidTargetFor(info), target, minApiVersion); + return (c == Compatibility.NO) ? false : true; + } + }; + } + + private IAndroidTarget getAndroidTargetFor(AvdInfo info) { + return sdkTargets.getTargetForSysImage((SystemImage)info.getSystemImage()); + } +} diff --git a/android-core/plugins/org.eclipse.andmore/src/org/eclipse/andmore/internal/launch/DeviceChooserDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/DeviceChooserDialog.java similarity index 87% rename from android-core/plugins/org.eclipse.andmore/src/org/eclipse/andmore/internal/launch/DeviceChooserDialog.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/DeviceChooserDialog.java index bd445ad1..d8502bfe 100644 --- a/android-core/plugins/org.eclipse.andmore/src/org/eclipse/andmore/internal/launch/DeviceChooserDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/DeviceChooserDialog.java @@ -1,824 +1,823 @@ -/* - * Copyright (C) 2007 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 org.eclipse.andmore.internal.launch; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.IDevice.DeviceState; -import com.android.ddmuilib.ImageLoader; -import com.android.ddmuilib.TableHelper; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; -import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter; - -import org.eclipse.andmore.ddms.DdmsPlugin; -import org.eclipse.andmore.internal.editors.IconFactory; -import org.eclipse.andmore.internal.sdk.AdtConsoleSdkLog; -import org.eclipse.andmore.internal.sdk.Sdk; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; - -import java.util.ArrayList; -import java.util.List; - -/** - * A dialog that lets the user choose a device to deploy an application. - * The user can either choose an exiting running device (including running emulators) - * or start a new emulator using an Android Virtual Device configuration that matches - * the current project. - */ -public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener { - - private final static int ICON_WIDTH = 16; - - private Table mDeviceTable; - private TableViewer mViewer; - private AvdSelector mPreferredAvdSelector; - - private Image mDeviceImage; - private Image mEmulatorImage; - private Image mMatchImage; - private Image mNoMatchImage; - private Image mWarningImage; - - private final DeviceChooserResponse mResponse; - private final String mPackageName; - private final IAndroidTarget mProjectTarget; - private final AndroidVersion mMinApiVersion; - private final Sdk mSdk; - - private Button mDeviceRadioButton; - private Button mUseDeviceForFutureLaunchesCheckbox; - private boolean mUseDeviceForFutureLaunches; - - private boolean mDisableAvdSelectionChange = false; - - /** - * Basic Content Provider for a table full of {@link IDevice} objects. The input is - * a {@link AndroidDebugBridge}. - */ - private class ContentProvider implements IStructuredContentProvider { - @Override - public Object[] getElements(Object inputElement) { - if (inputElement instanceof AndroidDebugBridge) { - return findCompatibleDevices(((AndroidDebugBridge)inputElement).getDevices()); - } - - return new Object[0]; - } - - private Object[] findCompatibleDevices(IDevice[] devices) { - if (devices == null) { - return null; - } - - List compatibleDevices = new ArrayList(devices.length); - for (IDevice device : devices) { - AndroidVersion deviceVersion = Sdk.getDeviceVersion(device); - if (deviceVersion == null || deviceVersion.canRun(mMinApiVersion)) { - compatibleDevices.add(device); - } - } - - return compatibleDevices.toArray(); - } - - @Override - public void dispose() { - // pass - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // pass - } - } - - /** - * A Label Provider for the {@link TableViewer} in {@link DeviceChooserDialog}. - * It provides labels and images for {@link IDevice} objects. - */ - private class LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - if (element instanceof IDevice) { - IDevice device = (IDevice)element; - switch (columnIndex) { - case 0: - return device.isEmulator() ? mEmulatorImage : mDeviceImage; - - case 2: - // check for compatibility. - if (device.isEmulator() == false) { // physical device - // get the version of the device - AndroidVersion deviceVersion = Sdk.getDeviceVersion(device); - if (deviceVersion == null) { - return mWarningImage; - } else { - if (!deviceVersion.canRun(mMinApiVersion)) { - return mNoMatchImage; - } - - // if the project is compiling against an add-on, - // the optional API may be missing from the device. - return mProjectTarget.isPlatform() ? - mMatchImage : mWarningImage; - } - } else { - // get the AvdInfo - AvdInfo info = mSdk.getAvdManager().getAvd(device.getAvdName(), - true /*validAvdOnly*/); - AvdCompatibility.Compatibility c = - AvdCompatibility.canRun(info, mProjectTarget, - mMinApiVersion); - switch (c) { - case YES: - return mMatchImage; - case NO: - return mNoMatchImage; - case UNKNOWN: - return mWarningImage; - } - } - } - } - - return null; - } - - @Override - public String getColumnText(Object element, int columnIndex) { - if (element instanceof IDevice) { - IDevice device = (IDevice)element; - switch (columnIndex) { - case 0: - return device.getName(); - case 1: - if (device.isEmulator()) { - return device.getAvdName(); - } else { - return "N/A"; // devices don't have AVD names. - } - case 2: - if (device.isEmulator()) { - AvdInfo info = mSdk.getAvdManager().getAvd(device.getAvdName(), - true /*validAvdOnly*/); - if (info == null) { - return "?"; - } - return info.getTarget().getFullName(); - } else { - String deviceBuild = device.getProperty(IDevice.PROP_BUILD_VERSION); - if (deviceBuild == null) { - return "unknown"; - } - return deviceBuild; - } - case 3: - String debuggable = device.getProperty(IDevice.PROP_DEBUGGABLE); - if (debuggable != null && debuggable.equals("1")) { //$NON-NLS-1$ - return "Yes"; - } else { - return ""; - } - case 4: - return getStateString(device); - } - } - - return null; - } - - @Override - public void addListener(ILabelProviderListener listener) { - // pass - } - - @Override - public void dispose() { - // pass - } - - @Override - public boolean isLabelProperty(Object element, String property) { - // pass - return false; - } - - @Override - public void removeListener(ILabelProviderListener listener) { - // pass - } - } - - public static class DeviceChooserResponse { - private AvdInfo mAvdToLaunch; - private IDevice mDeviceToUse; - private boolean mUseDeviceForFutureLaunches; - - public void setDeviceToUse(IDevice d) { - mDeviceToUse = d; - mAvdToLaunch = null; - } - - public void setAvdToLaunch(AvdInfo avd) { - mAvdToLaunch = avd; - mDeviceToUse = null; - } - - public IDevice getDeviceToUse() { - return mDeviceToUse; - } - - public AvdInfo getAvdToLaunch() { - return mAvdToLaunch; - } - - public void setUseDeviceForFutureLaunches(boolean en) { - mUseDeviceForFutureLaunches = en; - } - - public boolean useDeviceForFutureLaunches() { - return mUseDeviceForFutureLaunches; - } - } - - public DeviceChooserDialog(Shell parent, DeviceChooserResponse response, String packageName, - IAndroidTarget projectTarget, AndroidVersion minApiVersion, - boolean useDeviceForFutureLaunches) { - super(parent); - - mResponse = response; - mPackageName = packageName; - mProjectTarget = projectTarget; - mMinApiVersion = minApiVersion; - mSdk = Sdk.getCurrent(); - mUseDeviceForFutureLaunches = useDeviceForFutureLaunches; - - AndroidDebugBridge.addDeviceChangeListener(this); - loadImages(); - } - - private void cleanup() { - // done listening. - AndroidDebugBridge.removeDeviceChangeListener(this); - } - - @Override - protected void okPressed() { - cleanup(); - super.okPressed(); - } - - @Override - protected void cancelPressed() { - cleanup(); - super.cancelPressed(); - } - - @Override - protected Control createContents(Composite parent) { - Control content = super.createContents(parent); - - // this must be called after createContents() has happened so that the - // ok button has been created (it's created after the call to createDialogArea) - updateDefaultSelection(); - - return content; - } - - /** - * Create the button bar: We override the Dialog implementation of this method - * so that we can create the checkbox at the same level as the 'Cancel' and 'OK' buttons. - */ - @Override - protected Control createButtonBar(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - - GridLayout layout = new GridLayout(1, false); - layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mUseDeviceForFutureLaunchesCheckbox = new Button(composite, SWT.CHECK); - mUseDeviceForFutureLaunchesCheckbox.setSelection(mUseDeviceForFutureLaunches); - mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); - mUseDeviceForFutureLaunchesCheckbox.setText("Use same device for future launches"); - mUseDeviceForFutureLaunchesCheckbox.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - mUseDeviceForFutureLaunches = - mUseDeviceForFutureLaunchesCheckbox.getSelection(); - mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); - } - }); - mUseDeviceForFutureLaunchesCheckbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - createButton(composite, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - createButton(composite, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); - - return composite; - } - - @Override - protected Control createDialogArea(Composite parent) { - // set dialog title - getShell().setText("Android Device Chooser"); - - Composite top = new Composite(parent, SWT.NONE); - top.setLayout(new GridLayout(1, true)); - - String msg; - if (mProjectTarget.isPlatform()) { - msg = String.format("Select a device with min API level %s.", - mMinApiVersion.getApiString()); - } else { - msg = String.format("Select a device compatible with target %s.", - mProjectTarget.getFullName()); - } - Label label = new Label(top, SWT.NONE); - label.setText(msg); - - mDeviceRadioButton = new Button(top, SWT.RADIO); - mDeviceRadioButton.setText("Choose a running Android device"); - mDeviceRadioButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - boolean deviceMode = mDeviceRadioButton.getSelection(); - - mDeviceTable.setEnabled(deviceMode); - mPreferredAvdSelector.setEnabled(!deviceMode); - - if (deviceMode) { - handleDeviceSelection(); - } else { - mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected()); - } - - enableOkButton(); - } - }); - mDeviceRadioButton.setSelection(true); - - - // offset the selector from the radio button - Composite offsetComp = new Composite(top, SWT.NONE); - offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - GridLayout layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - offsetComp.setLayout(layout); - - mDeviceTable = new Table(offsetComp, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); - GridData gd; - mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); - gd.heightHint = 100; - - mDeviceTable.setHeaderVisible(true); - mDeviceTable.setLinesVisible(true); - - TableHelper.createTableColumn(mDeviceTable, "Serial Number", - SWT.LEFT, "AAA+AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "AVD Name", - SWT.LEFT, "AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "Target", - SWT.LEFT, "AAA+Android 9.9.9", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "Debug", - SWT.LEFT, "Debug", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "State", - SWT.LEFT, "bootloader", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - // create the viewer for it - mViewer = new TableViewer(mDeviceTable); - mViewer.setContentProvider(new ContentProvider()); - mViewer.setLabelProvider(new LabelProvider()); - mViewer.setInput(AndroidDebugBridge.getBridge()); - - mDeviceTable.addSelectionListener(new SelectionAdapter() { - /** - * Handles single-click selection on the device selector. - * {@inheritDoc} - */ - @Override - public void widgetSelected(SelectionEvent e) { - handleDeviceSelection(); - } - - /** - * Handles double-click selection on the device selector. - * Note that the single-click handler will probably already have been called. - * {@inheritDoc} - */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - handleDeviceSelection(); - if (isOkButtonEnabled()) { - okPressed(); - } - } - }); - - Button radio2 = new Button(top, SWT.RADIO); - radio2.setText("Launch a new Android Virtual Device"); - - // offset the selector from the radio button - offsetComp = new Composite(top, SWT.NONE); - offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - offsetComp.setLayout(layout); - - mPreferredAvdSelector = new AvdSelector(offsetComp, - mSdk.getSdkOsLocation(), - mSdk.getAvdManager(), - new NonRunningAvdFilter(), - DisplayMode.SIMPLE_SELECTION, - new AdtConsoleSdkLog()); - mPreferredAvdSelector.setTableHeightHint(100); - mPreferredAvdSelector.setEnabled(false); - mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { - /** - * Handles single-click selection on the AVD selector. - * {@inheritDoc} - */ - @Override - public void widgetSelected(SelectionEvent e) { - if (mDisableAvdSelectionChange == false) { - mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected()); - enableOkButton(); - } - } - - /** - * Handles double-click selection on the AVD selector. - * - * Note that the single-click handler will probably already have been called - * but the selected item can have changed in between. - * - * {@inheritDoc} - */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - if (isOkButtonEnabled()) { - okPressed(); - } - } - }); - - return top; - } - - private void loadImages() { - ImageLoader ddmUiLibLoader = ImageLoader.getDdmUiLibLoader(); - Display display = DdmsPlugin.getDisplay(); - IconFactory factory = IconFactory.getInstance(); - - if (mDeviceImage == null) { - mDeviceImage = ddmUiLibLoader.loadImage(display, - "device.png", //$NON-NLS-1$ - ICON_WIDTH, ICON_WIDTH, - display.getSystemColor(SWT.COLOR_RED)); - } - if (mEmulatorImage == null) { - mEmulatorImage = ddmUiLibLoader.loadImage(display, - "emulator.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_BLUE)); - } - - if (mMatchImage == null) { - mMatchImage = factory.getIcon("match", //$NON-NLS-1$ - IconFactory.COLOR_GREEN, - IconFactory.SHAPE_DEFAULT); - } - - if (mNoMatchImage == null) { - mNoMatchImage = factory.getIcon("error", //$NON-NLS-1$ - IconFactory.COLOR_RED, - IconFactory.SHAPE_DEFAULT); - } - - if (mWarningImage == null) { - mWarningImage = factory.getIcon("warning", //$NON-NLS-1$ - SWT.COLOR_YELLOW, - IconFactory.SHAPE_DEFAULT); - } - - } - - /** - * Returns a display string representing the state of the device. - * @param d the device - */ - private static String getStateString(IDevice d) { - DeviceState deviceState = d.getState(); - if (deviceState == DeviceState.ONLINE) { - return "Online"; - } else if (deviceState == DeviceState.OFFLINE) { - return "Offline"; - } else if (deviceState == DeviceState.BOOTLOADER) { - return "Bootloader"; - } - - return "??"; - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - *

- * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceConnected(IDevice) - */ - @Override - public void deviceConnected(IDevice device) { - final DeviceChooserDialog dialog = this; - exec(new Runnable() { - @Override - public void run() { - if (mDeviceTable.isDisposed() == false) { - // refresh all - mViewer.refresh(); - - // update the selection - updateDefaultSelection(); - - // update the display of AvdInfo (since it's filtered to only display - // non running AVD.) - refillAvdList(false /*reloadAvds*/); - } else { - // table is disposed, we need to do something. - // lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(dialog); - } - - } - }); - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - *

- * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceDisconnected(IDevice) - */ - @Override - public void deviceDisconnected(IDevice device) { - deviceConnected(device); - } - - /** - * Sent when a device data changed, or when clients are started/terminated on the device. - *

- * This is sent from a non UI thread. - * @param device the device that was updated. - * @param changeMask the mask indicating what changed. - * - * @see IDeviceChangeListener#deviceChanged(IDevice, int) - */ - @Override - public void deviceChanged(final IDevice device, int changeMask) { - if ((changeMask & (IDevice.CHANGE_STATE | IDevice.CHANGE_BUILD_INFO)) != 0) { - final DeviceChooserDialog dialog = this; - exec(new Runnable() { - @Override - public void run() { - if (mDeviceTable.isDisposed() == false) { - // refresh the device - mViewer.refresh(device); - - // update the defaultSelection. - updateDefaultSelection(); - - // update the display of AvdInfo (since it's filtered to only display - // non running AVD). This is done on deviceChanged because the avd name - // of a (emulator) device may be updated as the emulator boots. - - refillAvdList(false /*reloadAvds*/); - - // if the changed device is the current selection, - // we update the OK button based on its state. - if (device == mResponse.getDeviceToUse()) { - enableOkButton(); - } - - } else { - // table is disposed, we need to do something. - // lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(dialog); - } - } - }); - } - } - - /** - * Returns whether the dialog is in "device" mode (true), or in "avd" mode (false). - */ - private boolean isDeviceMode() { - return mDeviceRadioButton.getSelection(); - } - - /** - * Enables or disables the OK button of the dialog based on various selections in the dialog. - */ - private void enableOkButton() { - Button okButton = getButton(IDialogConstants.OK_ID); - - if (isDeviceMode()) { - okButton.setEnabled(mResponse.getDeviceToUse() != null && - mResponse.getDeviceToUse().isOnline()); - } else { - okButton.setEnabled(mResponse.getAvdToLaunch() != null); - } - } - - /** - * Returns true if the ok button is enabled. - */ - private boolean isOkButtonEnabled() { - Button okButton = getButton(IDialogConstants.OK_ID); - return okButton.isEnabled(); - } - - /** - * Executes the {@link Runnable} in the UI thread. - * @param runnable the runnable to execute. - */ - private void exec(Runnable runnable) { - try { - Display display = mDeviceTable.getDisplay(); - display.asyncExec(runnable); - } catch (SWTException e) { - // tree is disposed, we need to do something. lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(this); - } - } - - private void handleDeviceSelection() { - int count = mDeviceTable.getSelectionCount(); - if (count != 1) { - handleSelection(null); - } else { - int index = mDeviceTable.getSelectionIndex(); - Object data = mViewer.getElementAt(index); - if (data instanceof IDevice) { - handleSelection((IDevice)data); - } else { - handleSelection(null); - } - } - } - - private void handleSelection(IDevice device) { - mResponse.setDeviceToUse(device); - enableOkButton(); - } - - /** - * Look for a default device to select. This is done by looking for the running - * clients on each device and finding one similar to the one being launched. - *

- * This is done every time the device list changed unless there is a already selection. - */ - private void updateDefaultSelection() { - if (mDeviceTable.getSelectionCount() == 0) { - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - - IDevice[] devices = bridge.getDevices(); - - for (IDevice device : devices) { - Client[] clients = device.getClients(); - - for (Client client : clients) { - - if (mPackageName.equals(client.getClientData().getClientDescription())) { - // found a match! Select it. - mViewer.setSelection(new StructuredSelection(device)); - handleSelection(device); - - // and we're done. - return; - } - } - } - } - - handleDeviceSelection(); - } - - private final class NonRunningAvdFilter implements IAvdFilter { - - private IDevice[] mDevices; - - @Override - public void prepare() { - mDevices = AndroidDebugBridge.getBridge().getDevices(); - } - - @Override - public boolean accept(AvdInfo avd) { - if (mDevices != null) { - for (IDevice d : mDevices) { - // do not accept running avd's - if (avd.getName().equals(d.getAvdName())) { - return false; - } - - // only accept avd's that can actually run the project - AvdCompatibility.Compatibility c = - AvdCompatibility.canRun(avd, mProjectTarget, mMinApiVersion); - return (c == AvdCompatibility.Compatibility.NO) ? false : true; - } - } - - return true; - } - - @Override - public void cleanup() { - mDevices = null; - } - } - - /** - * Refills the AVD list keeping the current selection. - */ - private void refillAvdList(boolean reloadAvds) { - // save the current selection - AvdInfo selected = mPreferredAvdSelector.getSelected(); - - // disable selection change. - mDisableAvdSelectionChange = true; - - // refresh the list - mPreferredAvdSelector.refresh(false); - - // attempt to reselect the proper avd if needed - if (selected != null) { - if (mPreferredAvdSelector.setSelection(selected) == false) { - // looks like the selection is lost. this can happen if an emulator - // running the AVD that was selected was launched from outside of Eclipse). - mResponse.setAvdToLaunch(null); - enableOkButton(); - } - } - - // enable the selection change - mDisableAvdSelectionChange = false; - } -} - +/* + * Copyright (C) 2007 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.ui; + +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; +import com.android.ddmlib.Client; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.IDevice.DeviceState; +import com.android.ddmuilib.TableHelper; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.repository.targets.SystemImage; +import com.android.sdkuilib.internal.repository.avd.AvdAgent; +import com.android.sdkuilib.internal.repository.avd.SdkTargets; +import com.android.sdkuilib.internal.widgets.AvdSelector; +import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter; + +import org.eclipse.andmore.base.resources.IEditorIconFactory; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.sdktool.SdkCallAgent; +import org.eclipse.andmore.sdktool.SdkContext; +import org.eclipse.andmore.sdktool.Utilities; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; + +import java.util.ArrayList; +import java.util.List; + +/** + * A dialog that lets the user choose a device to deploy an application. + * The user can either choose an exiting running device (including running emulators) + * or start a new emulator using an Android Virtual Device configuration that matches + * the current project. + */ +public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener { + + private Table mDeviceTable; + private TableViewer mViewer; + private AvdSelector mPreferredAvdSelector; + + private Image mDeviceImage; + private Image mEmulatorImage; + private Image mMatchImage; + private Image mNoMatchImage; + private Image mWarningImage; + + private final DeviceChooserResponse mResponse; + private final String mPackageName; + private final IAndroidTarget mProjectTarget; + private final AndroidVersion mMinApiVersion; + private final SdkContext mSdkContext; + private final SdkTargets mSdkTargets; + private final IEditorIconFactory mIconFactory; + + private Button mDeviceRadioButton; + private Button mUseDeviceForFutureLaunchesCheckbox; + private boolean mUseDeviceForFutureLaunches; + + private boolean mDisableAvdSelectionChange = false; + + /** + * Basic Content Provider for a table full of {@link IDevice} objects. The input is + * a {@link AndroidDebugBridge}. + */ + private class ContentProvider implements IStructuredContentProvider { + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof AndroidDebugBridge) { + return findCompatibleDevices(((AndroidDebugBridge)inputElement).getDevices()); + } + + return new Object[0]; + } + + private Object[] findCompatibleDevices(IDevice[] devices) { + if (devices == null) { + return null; + } + + List compatibleDevices = new ArrayList(devices.length); + for (IDevice device : devices) { + AndroidVersion deviceVersion = Utilities.getDeviceVersion(device); + if (deviceVersion == null || deviceVersion.canRun(mMinApiVersion)) { + compatibleDevices.add(device); + } + } + + return compatibleDevices.toArray(); + } + + @Override + public void dispose() { + // pass + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // pass + } + } + + /** + * A Label Provider for the {@link TableViewer} in {@link DeviceChooserDialog}. + * It provides labels and images for {@link IDevice} objects. + */ + private class LabelProvider implements ITableLabelProvider { + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (element instanceof IDevice) { + IDevice device = (IDevice)element; + switch (columnIndex) { + case 0: + return device.isEmulator() ? mEmulatorImage : mDeviceImage; + + case 2: + // check for compatibility. + if (device.isEmulator() == false) { // physical device + // get the version of the device + AndroidVersion deviceVersion = Utilities.getDeviceVersion(device); + if (deviceVersion == null) { + return mWarningImage; + } else { + if (!deviceVersion.canRun(mMinApiVersion)) { + return mNoMatchImage; + } + + // if the project is compiling against an add-on, + // the optional API may be missing from the device. + return mProjectTarget.isPlatform() ? + mMatchImage : mWarningImage; + } + } else { + // get the AvdInfo + AvdInfo info = mSdkContext.getAvdManager().getAvd(device.getAvdName(), + true /*validAvdOnly*/); + if (info == null) + return mWarningImage; + IAndroidTarget avdTarget = getAndroidTargetFor(info); + Utilities.Compatibility c = + Utilities.canRun(info, mProjectTarget, avdTarget, mMinApiVersion); + switch (c) { + case YES: + return mMatchImage; + case NO: + return mNoMatchImage; + case UNKNOWN: + return mWarningImage; + } + } + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (element instanceof IDevice) { + IDevice device = (IDevice)element; + switch (columnIndex) { + case 0: + return device.getName(); + case 1: + if (device.isEmulator()) { + return device.getAvdName(); + } else { + return "N/A"; // devices don't have AVD names. + } + case 2: + if (device.isEmulator()) { + AvdInfo info = mSdkContext.getAvdManager().getAvd(device.getAvdName(), + true /*validAvdOnly*/); + if (info == null) { + return "?"; + } + return getAndroidTargetFor(info).getFullName(); + } else { + String deviceBuild = device.getProperty(IDevice.PROP_BUILD_VERSION); + if (deviceBuild == null) { + return "unknown"; + } + return deviceBuild; + } + case 3: + String debuggable = device.getProperty(IDevice.PROP_DEBUGGABLE); + if (debuggable != null && debuggable.equals("1")) { //$NON-NLS-1$ + return "Yes"; + } else { + return ""; + } + case 4: + return getStateString(device); + } + } + + return null; + } + + @Override + public void addListener(ILabelProviderListener listener) { + // pass + } + + @Override + public void dispose() { + // pass + } + + @Override + public boolean isLabelProperty(Object element, String property) { + // pass + return false; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + // pass + } + } + + public static class DeviceChooserResponse { + private AvdInfo mAvdToLaunch; + private IDevice mDeviceToUse; + private boolean mUseDeviceForFutureLaunches; + + public void setDeviceToUse(IDevice d) { + mDeviceToUse = d; + mAvdToLaunch = null; + } + + public void setAvdToLaunch(AvdInfo avd) { + mAvdToLaunch = avd; + mDeviceToUse = null; + } + + public IDevice getDeviceToUse() { + return mDeviceToUse; + } + + public AvdInfo getAvdToLaunch() { + return mAvdToLaunch; + } + + public void setUseDeviceForFutureLaunches(boolean en) { + mUseDeviceForFutureLaunches = en; + } + + public boolean useDeviceForFutureLaunches() { + return mUseDeviceForFutureLaunches; + } + } + + public DeviceChooserDialog(Shell parent, SdkCallAgent sdkCallAgent, DeviceChooserResponse response, String packageName, + IAndroidTarget projectTarget, AndroidVersion minApiVersion, + boolean useDeviceForFutureLaunches) { + super(parent); + + mSdkContext = sdkCallAgent.getSdkContext(); + mSdkTargets = new SdkTargets(mSdkContext); + mIconFactory = sdkCallAgent.getEditorIconFactory(); + mResponse = response; + mPackageName = packageName; + mProjectTarget = projectTarget; + mMinApiVersion = minApiVersion; + mUseDeviceForFutureLaunches = useDeviceForFutureLaunches; + + AndroidDebugBridge.addDeviceChangeListener(this); + loadImages(parent.getDisplay()); + } + + private void cleanup() { + // done listening. + AndroidDebugBridge.removeDeviceChangeListener(this); + } + + @Override + protected void okPressed() { + cleanup(); + super.okPressed(); + } + + @Override + protected void cancelPressed() { + cleanup(); + super.cancelPressed(); + } + + @Override + protected Control createContents(Composite parent) { + Control content = super.createContents(parent); + + // this must be called after createContents() has happened so that the + // ok button has been created (it's created after the call to createDialogArea) + updateDefaultSelection(); + + return content; + } + + /** + * Create the button bar: We override the Dialog implementation of this method + * so that we can create the checkbox at the same level as the 'Cancel' and 'OK' buttons. + */ + @Override + protected Control createButtonBar(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + + GridLayout layout = new GridLayout(1, false); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + mUseDeviceForFutureLaunchesCheckbox = new Button(composite, SWT.CHECK); + mUseDeviceForFutureLaunchesCheckbox.setSelection(mUseDeviceForFutureLaunches); + mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); + mUseDeviceForFutureLaunchesCheckbox.setText("Use same device for future launches"); + mUseDeviceForFutureLaunchesCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + mUseDeviceForFutureLaunches = + mUseDeviceForFutureLaunchesCheckbox.getSelection(); + mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); + } + }); + mUseDeviceForFutureLaunchesCheckbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + createButton(composite, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(composite, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + + return composite; + } + + @Override + protected Control createDialogArea(Composite parent) { + // set dialog title + getShell().setText("Android Device Chooser"); + + Composite top = new Composite(parent, SWT.NONE); + top.setLayout(new GridLayout(1, true)); + + String msg; + if (mProjectTarget.isPlatform()) { + msg = String.format("Select a device with min API level %s.", + mMinApiVersion.getApiString()); + } else { + msg = String.format("Select a device compatible with target %s.", + mProjectTarget.getFullName()); + } + Label label = new Label(top, SWT.NONE); + label.setText(msg); + + mDeviceRadioButton = new Button(top, SWT.RADIO); + mDeviceRadioButton.setText("Choose a running Android device"); + mDeviceRadioButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean deviceMode = mDeviceRadioButton.getSelection(); + + mDeviceTable.setEnabled(deviceMode); + mPreferredAvdSelector.setEnabled(!deviceMode); + + if (deviceMode) { + handleDeviceSelection(); + } else { + mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected().getAvd()); + } + + enableOkButton(); + } + }); + mDeviceRadioButton.setSelection(true); + + + // offset the selector from the radio button + Composite offsetComp = new Composite(top, SWT.NONE); + offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + GridLayout layout = new GridLayout(1, false); + layout.marginRight = layout.marginHeight = 0; + layout.marginLeft = 30; + offsetComp.setLayout(layout); + + mDeviceTable = new Table(offsetComp, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); + GridData gd; + mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); + gd.heightHint = 100; + + mDeviceTable.setHeaderVisible(true); + mDeviceTable.setLinesVisible(true); + + TableHelper.createTableColumn(mDeviceTable, "Serial Number", + SWT.LEFT, "AAA+AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ + null /* prefs name */, null /* prefs store */); + + TableHelper.createTableColumn(mDeviceTable, "AVD Name", + SWT.LEFT, "AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ + null /* prefs name */, null /* prefs store */); + + TableHelper.createTableColumn(mDeviceTable, "Target", + SWT.LEFT, "AAA+Android 9.9.9", //$NON-NLS-1$ + null /* prefs name */, null /* prefs store */); + + TableHelper.createTableColumn(mDeviceTable, "Debug", + SWT.LEFT, "Debug", //$NON-NLS-1$ + null /* prefs name */, null /* prefs store */); + + TableHelper.createTableColumn(mDeviceTable, "State", + SWT.LEFT, "bootloader", //$NON-NLS-1$ + null /* prefs name */, null /* prefs store */); + + // create the viewer for it + mViewer = new TableViewer(mDeviceTable); + mViewer.setContentProvider(new ContentProvider()); + mViewer.setLabelProvider(new LabelProvider()); + mViewer.setInput(AndroidDebugBridge.getBridge()); + + mDeviceTable.addSelectionListener(new SelectionAdapter() { + /** + * Handles single-click selection on the device selector. + * {@inheritDoc} + */ + @Override + public void widgetSelected(SelectionEvent e) { + handleDeviceSelection(); + } + + /** + * Handles double-click selection on the device selector. + * Note that the single-click handler will probably already have been called. + * {@inheritDoc} + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + handleDeviceSelection(); + if (isOkButtonEnabled()) { + okPressed(); + } + } + }); + + Button radio2 = new Button(top, SWT.RADIO); + radio2.setText("Launch a new Android Virtual Device"); + + // offset the selector from the radio button + offsetComp = new Composite(top, SWT.NONE); + offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + layout = new GridLayout(1, false); + layout.marginRight = layout.marginHeight = 0; + layout.marginLeft = 30; + offsetComp.setLayout(layout); + + mPreferredAvdSelector = new AvdSelector(offsetComp, + mSdkContext, + new NonRunningAvdFilter(), + AvdDisplayMode.SIMPLE_SELECTION); + mPreferredAvdSelector.setTableHeightHint(100); + mPreferredAvdSelector.setEnabled(false); + mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { + /** + * Handles single-click selection on the AVD selector. + * {@inheritDoc} + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (mDisableAvdSelectionChange == false) { + mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected().getAvd()); + enableOkButton(); + } + } + + /** + * Handles double-click selection on the AVD selector. + * + * Note that the single-click handler will probably already have been called + * but the selected item can have changed in between. + * + * {@inheritDoc} + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + if (isOkButtonEnabled()) { + okPressed(); + } + } + }); + + return top; + } + + private void loadImages(Display display) { + ImageFactory imageFactory = mSdkContext.getSdkHelper().getImageFactory(); + + if (mDeviceImage == null) { + mDeviceImage = imageFactory.getImageByName("device.png"); //$NON-NLS-1$ + } + if (mEmulatorImage == null) { + mEmulatorImage = imageFactory.getImageByName("emulator.png"); //$NON-NLS-1$ + } + + if (mMatchImage == null) { + mMatchImage = mIconFactory.getColorIcon("match", //$NON-NLS-1$ + SWT.COLOR_DARK_GREEN); + } + + if (mNoMatchImage == null) { + mNoMatchImage = mIconFactory.getColorIcon("error", //$NON-NLS-1$ + SWT.COLOR_DARK_RED); + } + + if (mWarningImage == null) { + mWarningImage = mIconFactory.getColorIcon("warning", //$NON-NLS-1$ + SWT.COLOR_YELLOW); + } + + } + + /** + * Returns a display string representing the state of the device. + * @param d the device + */ + private static String getStateString(IDevice d) { + DeviceState deviceState = d.getState(); + if (deviceState == DeviceState.ONLINE) { + return "Online"; + } else if (deviceState == DeviceState.OFFLINE) { + return "Offline"; + } else if (deviceState == DeviceState.BOOTLOADER) { + return "Bootloader"; + } + + return "??"; + } + + /** + * Sent when the a device is connected to the {@link AndroidDebugBridge}. + *

+ * This is sent from a non UI thread. + * @param device the new device. + * + * @see IDeviceChangeListener#deviceConnected(IDevice) + */ + @Override + public void deviceConnected(IDevice device) { + final DeviceChooserDialog dialog = this; + exec(new Runnable() { + @Override + public void run() { + if (mDeviceTable.isDisposed() == false) { + // refresh all + mViewer.refresh(); + + // update the selection + updateDefaultSelection(); + + // update the display of AvdInfo (since it's filtered to only display + // non running AVD.) + refillAvdList(false /*reloadAvds*/); + } else { + // table is disposed, we need to do something. + // lets remove ourselves from the listener. + AndroidDebugBridge.removeDeviceChangeListener(dialog); + } + + } + }); + } + + /** + * Sent when the a device is connected to the {@link AndroidDebugBridge}. + *

+ * This is sent from a non UI thread. + * @param device the new device. + * + * @see IDeviceChangeListener#deviceDisconnected(IDevice) + */ + @Override + public void deviceDisconnected(IDevice device) { + deviceConnected(device); + } + + /** + * Sent when a device data changed, or when clients are started/terminated on the device. + *

+ * This is sent from a non UI thread. + * @param device the device that was updated. + * @param changeMask the mask indicating what changed. + * + * @see IDeviceChangeListener#deviceChanged(IDevice, int) + */ + @Override + public void deviceChanged(final IDevice device, int changeMask) { + if ((changeMask & (IDevice.CHANGE_STATE | IDevice.CHANGE_BUILD_INFO)) != 0) { + final DeviceChooserDialog dialog = this; + exec(new Runnable() { + @Override + public void run() { + if (mDeviceTable.isDisposed() == false) { + // refresh the device + mViewer.refresh(device); + + // update the defaultSelection. + updateDefaultSelection(); + + // update the display of AvdInfo (since it's filtered to only display + // non running AVD). This is done on deviceChanged because the avd name + // of a (emulator) device may be updated as the emulator boots. + + refillAvdList(false /*reloadAvds*/); + + // if the changed device is the current selection, + // we update the OK button based on its state. + if (device == mResponse.getDeviceToUse()) { + enableOkButton(); + } + + } else { + // table is disposed, we need to do something. + // lets remove ourselves from the listener. + AndroidDebugBridge.removeDeviceChangeListener(dialog); + } + } + }); + } + } + + /** + * Returns whether the dialog is in "device" mode (true), or in "avd" mode (false). + */ + private boolean isDeviceMode() { + return mDeviceRadioButton.getSelection(); + } + + /** + * Enables or disables the OK button of the dialog based on various selections in the dialog. + */ + private void enableOkButton() { + Button okButton = getButton(IDialogConstants.OK_ID); + + if (isDeviceMode()) { + okButton.setEnabled(mResponse.getDeviceToUse() != null && + mResponse.getDeviceToUse().isOnline()); + } else { + okButton.setEnabled(mResponse.getAvdToLaunch() != null); + } + } + + /** + * Returns true if the ok button is enabled. + */ + private boolean isOkButtonEnabled() { + Button okButton = getButton(IDialogConstants.OK_ID); + return okButton.isEnabled(); + } + + /** + * Executes the {@link Runnable} in the UI thread. + * @param runnable the runnable to execute. + */ + private void exec(Runnable runnable) { + try { + Display display = mDeviceTable.getDisplay(); + display.asyncExec(runnable); + } catch (SWTException e) { + // tree is disposed, we need to do something. lets remove ourselves from the listener. + AndroidDebugBridge.removeDeviceChangeListener(this); + } + } + + private void handleDeviceSelection() { + int count = mDeviceTable.getSelectionCount(); + if (count != 1) { + handleSelection(null); + } else { + int index = mDeviceTable.getSelectionIndex(); + Object data = mViewer.getElementAt(index); + if (data instanceof IDevice) { + handleSelection((IDevice)data); + } else { + handleSelection(null); + } + } + } + + private void handleSelection(IDevice device) { + mResponse.setDeviceToUse(device); + enableOkButton(); + } + + /** + * Look for a default device to select. This is done by looking for the running + * clients on each device and finding one similar to the one being launched. + *

+ * This is done every time the device list changed unless there is a already selection. + */ + private void updateDefaultSelection() { + if (mDeviceTable.getSelectionCount() == 0) { + AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); + + IDevice[] devices = bridge.getDevices(); + + for (IDevice device : devices) { + Client[] clients = device.getClients(); + + for (Client client : clients) { + + if (mPackageName.equals(client.getClientData().getClientDescription())) { + // found a match! Select it. + mViewer.setSelection(new StructuredSelection(device)); + handleSelection(device); + + // and we're done. + return; + } + } + } + } + + handleDeviceSelection(); + } + + private final class NonRunningAvdFilter implements IAvdFilter { + + private IDevice[] mDevices; + + @Override + public void prepare() { + mDevices = AndroidDebugBridge.getBridge().getDevices(); + } + + @Override + public boolean accept(AvdAgent avdAgent) { + AvdInfo info = avdAgent.getAvd(); + if (mDevices != null) { + for (IDevice d : mDevices) { + // do not accept running avd's + if (info.getName().equals(d.getAvdName())) { + return false; + } + + // only accept avd's that can actually run the project + Utilities.Compatibility c = + Utilities.canRun(avdAgent.getAvd(), getAndroidTargetFor(info), mProjectTarget, mMinApiVersion); + return (c == Utilities.Compatibility.NO) ? false : true; + } + } + + return true; + } + + @Override + public void cleanup() { + mDevices = null; + } + } + + /** + * Refills the AVD list keeping the current selection. + */ + private void refillAvdList(boolean reloadAvds) { + // save the current selection + AvdAgent selected = mPreferredAvdSelector.getSelected(); + + // disable selection change. + mDisableAvdSelectionChange = true; + + // refresh the list + mPreferredAvdSelector.refresh(false); + + // attempt to reselect the proper avd if needed + if (selected != null) { + if (mPreferredAvdSelector.setSelection(selected) == false) { + // looks like the selection is lost. this can happen if an emulator + // running the AVD that was selected was launched from outside of Eclipse). + mResponse.setAvdToLaunch(null); + enableOkButton(); + } + } + + // enable the selection change + mDisableAvdSelectionChange = false; + } + + private IAndroidTarget getAndroidTargetFor(AvdInfo info) { + return mSdkTargets.getTargetForSysImage((SystemImage)info.getSystemImage()); + } +} + diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/ResolutionChooserDialog.java similarity index 95% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/ResolutionChooserDialog.java index e5e1d6cf..a835014d 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/ui/ResolutionChooserDialog.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.widgets; - -import com.android.sdkuilib.ui.GridDialog; +package com.android.sdkuilib.ui; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/MessageBoxLog.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/MessageBoxLog.java similarity index 95% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/MessageBoxLog.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/MessageBoxLog.java index 68463ee0..e7b9d4c8 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/MessageBoxLog.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/MessageBoxLog.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.widgets; +package com.android.sdkuilib.widgets; import com.android.annotations.NonNull; +import com.android.sdkuilib.internal.widgets.IMessageBoxLogger; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/SdkTargetSelector.java similarity index 96% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java rename to andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/SdkTargetSelector.java index bee160f6..5634cde5 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdkuilib/widgets/SdkTargetSelector.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.sdkuilib.internal.widgets; +package com.android.sdkuilib.widgets; import com.android.SdkConstants; import com.android.sdklib.IAndroidTarget; diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkCallAgent.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkCallAgent.java new file mode 100644 index 00000000..bed8f6fc --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkCallAgent.java @@ -0,0 +1,96 @@ +/** + * + */ +package org.eclipse.andmore.sdktool; + +import org.eclipse.andmore.base.resources.IEditorIconFactory; +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.base.resources.JFaceImageLoader; +import org.eclipse.andmore.base.resources.PluginResourceProvider; +import org.eclipse.swt.graphics.Image; + +import com.android.repository.api.RepoManager; +import com.android.sdklib.repository.AndroidSdkHandler; +import com.android.utils.ILogger; + +/** + * @author andrew + * + */ +public class SdkCallAgent { + public static final int NO_TOOLS_MSG = 0; + public static final int TOOLS_MSG_UPDATED_FROM_ADT = 1; + public static final int TOOLS_MSG_UPDATED_FROM_SDKMAN = 2; + + private final SdkContext sdkContext; + private final ILogger consoleLogger; + private IEditorIconFactory iconEditorFactory; + + /** + * Construct SdkCallAgent object to mediate between application and UI layer + * @param sdkHandler SDK handler + * @param repoManager Repository manager + * @param consoleLogger Console logger to persist all messages + */ + public SdkCallAgent( + AndroidSdkHandler sdkHandler, + RepoManager repoManager, + ILogger consoleLogger) + { + this.sdkContext = new SdkContext(sdkHandler, repoManager); + sdkContext.setSdkLogger(consoleLogger); + this.consoleLogger = consoleLogger; + } + + /** + * Construct SdkCallAgent object to mediate between application and UI layer requiring an icon factory + * @param sdkHandler SDK handler + * @param repoManager Repository manager + * @param iconEditorFactory Icon factory to provide editor icons + * @param consoleLogger Console logger to persist all messages + */ + public SdkCallAgent( + AndroidSdkHandler sdkHandler, + RepoManager repoManager, + IEditorIconFactory iconEditorFactory, + ILogger consoleLogger) + { + this(sdkHandler, repoManager, consoleLogger); + this.iconEditorFactory = iconEditorFactory; + } + + public SdkContext getSdkContext() { + SdkHelper helper = sdkContext.getSdkHelper(); + if (helper.getImageFactory() == null) + helper.setImageFactory(getImageLoader(new SdkResourceProvider())); + return sdkContext; + } + + public IEditorIconFactory getEditorIconFactory() { + if (iconEditorFactory ==null) + // Icon factory not set. Do not throw exception, but handle gracefully. + return new IEditorIconFactory(){ + + @Override + public Image getColorIcon(String osName, int color) { + // Return generic image to avoid NPE + return sdkContext.getSdkHelper().getImageByName("nopkg_icon_16.png"); + }};// + return iconEditorFactory; + } + + public void dispose() + { + sdkContext.getSdkHelper().dispose(); + } + + /** + * Set image loader if not already set + */ + public ImageFactory getImageLoader(PluginResourceProvider provider) + { + JFaceImageLoader imageLoader = new JFaceImageLoader(provider); + imageLoader.setLogger(consoleLogger); + return imageLoader; + } +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkContext.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkContext.java new file mode 100644 index 00000000..ca3bbd0b --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkContext.java @@ -0,0 +1,208 @@ +package org.eclipse.andmore.sdktool; + +import java.io.File; +import java.util.ArrayList; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.prefs.AndroidLocation; +import com.android.repository.api.LocalPackage; +import com.android.repository.api.ProgressIndicator; +import com.android.repository.api.ProgressIndicatorAdapter; +import com.android.repository.api.RemotePackage; +import com.android.repository.api.RepoManager; +import com.android.repository.impl.meta.RepositoryPackages; +import com.android.repository.io.FileOp; +import com.android.sdklib.devices.DeviceManager; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.repository.AndroidSdkHandler; +import com.android.sdkuilib.internal.repository.PackageManager; +import com.android.sdkuilib.internal.repository.Settings; +import com.android.utils.ILogger; + +public class SdkContext { + + private final AndroidSdkHandler handler; + private final RepoManager repoManager; + private final DeviceManager deviceManager; + private final PackageManager packageManager; + private final SdkHelper sdkHelper; + private final AtomicBoolean hasWarning = new AtomicBoolean(); + private final AtomicBoolean hasError = new AtomicBoolean(); + private final ArrayList logMessages = new ArrayList(); + private Settings settings; + private ProgressIndicator sdkProgressIndicator; + private ILogger sdkLogger; + + public SdkContext(AndroidSdkHandler handler, RepoManager repoManager) { + super(); + this.handler = handler; + this.repoManager = repoManager; + this.sdkHelper = new SdkHelper(); + deviceManager = DeviceManager.createInstance(handler.getLocation(), loggerInstance()); + packageManager = new PackageManager(this); + } + + public void setSettings(Settings settings) + { + this.settings = settings; + } + + public Settings getSettings() + { + if (settings == null) + settings = new Settings(); + return settings; + } + + public PackageManager getPackageManager() + { + return packageManager; + } + public SdkHelper getSdkHelper() + { + return sdkHelper; + } + + public AndroidSdkHandler getHandler() { + return handler; + } + + public RepoManager getRepoManager() { + return repoManager; + } + + public AvdManager getAvdManager() + { + String avdFolder = null; + AvdManager avdManager = null; + ILogger logger = loggerInstance(); + try { + avdFolder = AndroidLocation.getAvdFolder(); + avdManager = AvdManager.getInstance(handler, new File(avdFolder), logger); + } catch (AndroidLocation.AndroidLocationException e) { + logger.error(e, "Error obtaining AVD Manager"); + } + return avdManager; + } + + public RepositoryPackages getPackages() { + return repoManager.getPackages(); + } + + public FileOp getFileOp() { + return handler.getFileOp(); + } + + public File getLocalPath() { + return repoManager.getLocalPath(); + } + + public File getLocation() { + return handler.getLocation(); + } + + public Map getRemotePackages() { + return getPackages().getRemotePackages(); + } + + public Map getLocalPackages() { + return getPackages().getLocalPackages(); + } + + public DeviceManager getDeviceManager() { + return deviceManager; + } + + public boolean hasWarning() { + return hasWarning.get(); + } + + public boolean hasError() { + return hasError.get(); + } + + public ArrayList getLogMessages() { + return logMessages; + } + + public ILogger loggerInstance() { + hasWarning.set(false); + hasError.set(false); + logMessages.clear(); + return new ILogger() { + @Override + public void error(@Nullable Throwable throwable, @Nullable String errorFormat, + Object... arg) { + hasError.set(true); + if (errorFormat != null) { + logMessages.add(String.format("Error: " + errorFormat, arg)); + } + + if (throwable != null) { + logMessages.add(throwable.getMessage()); + } + } + + @Override + public void warning(@NonNull String warningFormat, Object... arg) { + hasWarning.set(true); + logMessages.add(String.format("Warning: " + warningFormat, arg)); + } + + @Override + public void info(@NonNull String msgFormat, Object... arg) { + logMessages.add(String.format(msgFormat, arg)); + } + + @Override + public void verbose(@NonNull String msgFormat, Object... arg) { + info(msgFormat, arg); + } + }; + + } + + public void setSdkProgressIndicator(ProgressIndicator sdkProgressIndicator) { + this.sdkProgressIndicator = sdkProgressIndicator; + } + + public void setSdkLogger(ILogger sdkLogger) { + this.sdkLogger = sdkLogger; + } + + public ProgressIndicator getProgressIndicator() { + if (sdkProgressIndicator != null) + return sdkProgressIndicator; + return new ProgressIndicatorAdapter() + { + ILogger logger = getSdkLog(); + @Override + public void logWarning(@NonNull String s, @Nullable Throwable e) { + if (s != null) + logger.warning(s); + if (e != null) + logger.warning(e.getMessage()); + } + + @Override + public void logError(@NonNull String s, @Nullable Throwable e) { + logger.error(e, s); + } + + @Override + public void logInfo(@NonNull String s) { + logger.info(s); + } + }; + } + + public ILogger getSdkLog() { + if (sdkLogger != null) + return sdkLogger; + return loggerInstance(); + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkHelper.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkHelper.java new file mode 100644 index 00000000..5a3e7565 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkHelper.java @@ -0,0 +1,108 @@ +package org.eclipse.andmore.sdktool; + +import java.util.ArrayList; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.sdkuilib.repository.ISdkChangeListener; +import com.android.utils.ILogger; + +public class SdkHelper { + private Shell mWindowShell; + + /** The current {@link ImageFactory}. */ + private ImageFactory mImageFactory; + + private final ArrayList mListeners = new ArrayList(); + + /** Adds a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ + public void addListeners(ISdkChangeListener listener) { + if (mListeners.contains(listener) == false) { + mListeners.add(listener); + } + } + + /** Removes a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ + public void removeListener(ISdkChangeListener listener) { + mListeners.remove(listener); + } + + /** + * Safely invoke all the registered {@link ISdkChangeListener#onSdkLoaded()}. + * This can be called from any thread. + */ + public void broadcastOnSdkLoaded(ILogger logger) { + if (!mListeners.isEmpty()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + for (ISdkChangeListener listener : mListeners) { + try { + listener.onSdkLoaded(); + } catch (Throwable t) { + logger.error(t, null); + } + } + } + }); + } + } + + public void setWindowShell(Shell windowShell) { + mWindowShell = windowShell; + } + + public Shell getWindowShell() { + return mWindowShell; + } + + public void setImageFactory(ImageFactory imageFactory) { + mImageFactory = imageFactory; + } + + /** + * Returns image factory. + * @return ImageFactory object + */ + public ImageFactory getImageFactory() { + return mImageFactory; + } + + public void dispose() { + if (mImageFactory != null) + mImageFactory.dispose(); + } + /** + * Loads an image given its filename (with its extension). + * Might return null if the image cannot be loaded.
+ * The image is cached. Successive calls will return the same object.
+ * The image is automatically disposed when {@link ImageFactory} is disposed. + * + * @param imageName The filename (with extension) of the image to load. + * @return A new or existing {@link Image}. The caller must NOT dispose the image (the + * image will disposed by {@link #dispose()}). The returned image can be null if the + * expected file is missing. + */ + @Nullable + public Image getImageByName(@NonNull String imageName) { + return mImageFactory != null ? mImageFactory.getImageByName(imageName, imageName, null) : null; + } + + /** + * Runs the runnable on the UI thread using {@link Display#syncExec(Runnable)}. + * + * @param r Non-null runnable. + */ + protected void runOnUiThread(@NonNull Runnable r) { + if (mWindowShell != null && !mWindowShell.isDisposed()) { + mWindowShell.getDisplay().syncExec(r); + } + } + + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkResourceProvider.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkResourceProvider.java new file mode 100644 index 00000000..c1f49235 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkResourceProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.sdktool; + +import org.eclipse.andmore.base.resources.PluginResourceProvider; +import org.eclipse.jface.resource.ImageDescriptor; + +public class SdkResourceProvider implements PluginResourceProvider { + + @Override + public ImageDescriptor descriptorFromPath(String imagePath) { + return SdkUserInterfacePlugin.getImageDescriptor(imagePath); + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkUserInterfacePlugin.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkUserInterfacePlugin.java new file mode 100644 index 00000000..9ec6e6f6 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/SdkUserInterfacePlugin.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.sdktool; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * Plugin activator to manage resources such as images + * @author Andrew Bowley + * + */ +public class SdkUserInterfacePlugin extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "org.eclipse.andmore.sdkuilib"; //$NON-NLS-1$ + + private static SdkUserInterfacePlugin instance; + + public SdkUserInterfacePlugin() { + super(); + instance = this; + } + + public static SdkUserInterfacePlugin instance() + { + return instance; + } + + /** + * Starts up this plug-in. + *

+ * This method should be overridden in subclasses that need to do something + * when this plug-in is started. Implementors should call the inherited method + * at the first possible point to ensure that any system requirements can be met. + *

+ *

+ * If this method throws an exception, it is taken as an indication that + * plug-in initialization has failed; as a result, the plug-in will not + * be activated; moreover, the plug-in will be marked as disabled and + * ineligible for activation for the duration. + *

+ *

+ * Note 1: This method is automatically invoked by the platform + * the first time any code in the plug-in is executed. + *

+ *

+ * Note 2: This method is intended to perform simple initialization + * of the plug-in environment. The platform may terminate initializers + * that do not complete in a timely fashion. + *

+ *

+ * Note 3: The class loader typically has monitors acquired during invocation of this method. It is + * strongly recommended that this method avoid synchronized blocks or other thread locking mechanisms, + * as this would lead to deadlock vulnerability. + *

+ *

+ * Note 4: The supplied bundle context represents the plug-in to the OSGi framework. + * For security reasons, it is strongly recommended that this object should not be divulged. + *

+ *

+ * Note 5: This method and the {@link #stop(BundleContext)} may be called from separate threads, + * but the OSGi framework ensures that both methods will not be called simultaneously. + *

+ * Clients must never explicitly call this method. + * + * @param context the bundle context for this plug-in + * @exception Exception if this plug-in did not start up properly + * @since 3.0 + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /** + * Stops this plug-in. + *

+ * This method should be re-implemented in subclasses that need to do something + * when the plug-in is shut down. Implementors should call the inherited method + * as late as possible to ensure that any system requirements can be met. + *

+ *

+ * Plug-in shutdown code should be robust. In particular, this method + * should always make an effort to shut down the plug-in. Furthermore, + * the code should not assume that the plug-in was started successfully. + *

+ *

+ * Note 1: If a plug-in has been automatically started, this method will be automatically + * invoked by the platform when the platform is shut down. + *

+ *

+ * Note 2: This method is intended to perform simple termination + * of the plug-in environment. The platform may terminate invocations + * that do not complete in a timely fashion. + *

+ *

+ * Note 3: The supplied bundle context represents the plug-in to the OSGi framework. + * For security reasons, it is strongly recommended that this object should not be divulged. + *

+ *

+ * Note 4: This method and the {@link #start(BundleContext)} may be called from separate threads, + * but the OSGi framework ensures that both methods will not be called simultaneously. + *

+ * Clients must never explicitly call this method. + * + * @param context the bundle context for this plug-in + * @exception Exception if this method fails to shut down this plug-in + * @since 3.0 + */ + @Override + public void stop(BundleContext context) throws Exception { + super.stop(context); + } + + /** + * Returns an image descriptor for the image file at the given plug-in + * relative path + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/Utilities.java b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/Utilities.java new file mode 100644 index 00000000..b3e31e1b --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/org/eclipse/andmore/sdktool/Utilities.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.sdktool; + +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.ddmlib.IDevice; +import com.android.sdklib.AndroidVersion; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.devices.Device; +import com.android.sdklib.internal.avd.AvdInfo; + +/** + * @author Andrew Bowley + * + * 11-11-2017 + */ +public class Utilities { + public enum Compatibility { + YES, + NO, + UNKNOWN, + }; + + /** + * Format file size given value as number of bytes. + * Taken from deprecated Archive class + * @param size Number of bytes + * @return text size formatted according to scale up to gigabytes + */ + public static String formatFileSize(long size) { + String sizeStr; + if (size < 1024) { + sizeStr = String.format("%d Bytes", size); + } else if (size < 1024 * 1024) { + sizeStr = String.format("%d KiB", Math.round(size / 1024.0)); + } else if (size < 1024 * 1024 * 1024) { + sizeStr = String.format("%.1f MiB", + Math.round(10.0 * size / (1024 * 1024.0))/ 10.0); + } else { + sizeStr = String.format("%.1f GiB", + Math.round(10.0 * size / (1024 * 1024 * 1024.0))/ 10.0); + } + + return String.format("Size: %1$s", sizeStr); + } + + + @Nullable + public static AndroidVersion getDeviceVersion(@NonNull IDevice device) { + try { + Future future = device.getSystemProperty(IDevice.PROP_BUILD_API_LEVEL); + String apiLevel = null; + apiLevel = future.get(); + if (apiLevel == null) { + return null; + } + future = device.getSystemProperty(IDevice.PROP_BUILD_CODENAME); + return new AndroidVersion(Integer.parseInt(apiLevel), + future.get()); + } catch (NumberFormatException | InterruptedException | ExecutionException e) { + return null; + } + } + + /** + * Returns whether the specified AVD can run the given project that is built against + * a particular SDK and has the specified minApiLevel. + * @param avd AVD to check compatibility for + * @param avdTarget AVD target + * @param projectTarget project build target + * @param minApiVersion project min api level + * @return whether the given AVD can run the given application + */ + public static Compatibility canRun(AvdInfo avd, IAndroidTarget avdTarget, IAndroidTarget projectTarget, + AndroidVersion minApiVersion) { + if (avd == null) { + return Compatibility.UNKNOWN; + } + + if (avdTarget == null) { + return Compatibility.UNKNOWN; + } + + // for platform targets, we only need to check the min api version + if (projectTarget.isPlatform()) { + return avdTarget.getVersion().canRun(minApiVersion) ? + Compatibility.YES : Compatibility.NO; + } + + // for add-on targets, delegate to the add on target to check for compatibility + return projectTarget.canRunOn(avdTarget) ? Compatibility.YES : Compatibility.NO; + } +} diff --git a/andmore-swt/org.eclipse.andmore.swt/.classpath b/andmore-swt/org.eclipse.andmore.swt/.classpath index 54f49f95..2349129f 100644 --- a/andmore-swt/org.eclipse.andmore.swt/.classpath +++ b/andmore-swt/org.eclipse.andmore.swt/.classpath @@ -13,7 +13,7 @@ - + diff --git a/andmore-swt/org.eclipse.andmore.swt/META-INF/MANIFEST.MF b/andmore-swt/org.eclipse.andmore.swt/META-INF/MANIFEST.MF index 65bf4bfc..98b977f9 100644 --- a/andmore-swt/org.eclipse.andmore.swt/META-INF/MANIFEST.MF +++ b/andmore-swt/org.eclipse.andmore.swt/META-INF/MANIFEST.MF @@ -29,11 +29,17 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: com.android, com.android.annotations, com.android.annotations.concurrency, + com.android.ddmlib, + com.android.ddmlib.log, + com.android.ddmlib.logcat, + com.android.ddmlib.testrunner, + com.android.ddmlib.utils, com.android.dvlib, com.android.ide.common.blame, com.android.ide.common.internal, com.android.ide.common.rendering, com.android.ide.common.rendering.api, + com.android.ide.common.repository, com.android.ide.common.res2, com.android.ide.common.resources, com.android.ide.common.resources.configuration, @@ -44,15 +50,12 @@ Export-Package: com.android, com.android.prefs, com.android.repository, com.android.repository.api, + com.android.repository.impl.meta, com.android.repository.io, + com.android.repository.io.impl, com.android.repository.testframework, com.android.repository.util, com.android.resources, - com.android.ddmlib, - com.android.ddmlib.log, - com.android.ddmlib.logcat, - com.android.ddmlib.testrunner, - com.android.ddmlib.utils, com.android.sdklib, com.android.sdklib.build, com.android.sdklib.devices, @@ -60,6 +63,7 @@ Export-Package: com.android, com.android.sdklib.internal.build, com.android.sdklib.internal.project, com.android.sdklib.repository, + com.android.sdklib.repository.legacy, com.android.sdklib.repository.legacy.remote.internal, com.android.sdklib.repository.meta, com.android.sdklib.repository.targets, @@ -83,6 +87,7 @@ Export-Package: com.android, org.apache.http.entity.mime, org.apache.http.entity.mime.content, org.eclipse.andmore.base, + org.eclipse.andmore.base.resources, org.kxml2.io, org.kxml2.kdom, org.kxml2.wap, diff --git a/andmore-swt/org.eclipse.andmore.swt/pom.xml b/andmore-swt/org.eclipse.andmore.swt/pom.xml index 3e48751e..099e30e4 100644 --- a/andmore-swt/org.eclipse.andmore.swt/pom.xml +++ b/andmore-swt/org.eclipse.andmore.swt/pom.xml @@ -211,11 +211,6 @@ 4.1 - com.android.tools - sdk-common - ${android.tools.version} - - com.android.tools repository ${android.tools.version} diff --git a/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/IEditorIconFactory.java b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/IEditorIconFactory.java new file mode 100644 index 00000000..278ad4f1 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/IEditorIconFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.base.resources; + +import org.eclipse.swt.graphics.Image; + +/** + * Interface for Factory to generate icons for Android Editors + * @author Andrew Bowley + * + */ +public interface IEditorIconFactory { + + /** + * Returns an Image for a given icon name. + *

+ * Callers should not dispose it. + * + * @param osName The leaf name, without the extension, of an existing icon in the + * editor's "icons" directory. If it doesn't exist, a default icon will be + * generated automatically based on the name. + * @param color The color of the text in the automatically generated icons + */ + Image getColorIcon(String osName, int color); +} diff --git a/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/ImageFactory.java b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/ImageFactory.java new file mode 100644 index 00000000..c1b337a7 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/ImageFactory.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.base.resources; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; + +public interface ImageFactory { + /** + * Produces an edited version of given image + * {@link ImageFactory#getImageByName(String, String, ImageEditor)}. + */ + public interface ImageEditor { + /** + * The editor implementation needs to create an image data object based on a given image, or
+ * if no modification is necessary, return null.
+ *

+ * + * @param source A non-null source image. + * @return {@link ImageData} object, which can be null if no change required + */ + @NonNull public ImageData edit(@NonNull Image source); + } + + /** + * Produces an replacement version of given image + * {@link ImageFactory#getImageByName(String, String, Filter)}. + */ + public interface ReplacementImager { + /** + * The editor implementation needs to create an image data object based on a given image, or
+ * if no modification is necessary, return null.
+ *

+ * + * @param source A non-null source image. + * @return {@link ImageData} object, which can be null if no change required + */ + @NonNull public ImageData create(); + } + + /** + * Loads an image given its filename (with its extension). + * Might return null if the image cannot be loaded.
+ * The image is cached. Successive calls will return the same object.
+ * + * @param imageName The filename (with extension) of the image to load. + * @return {@link Image} object or null if the image file is not found. The caller must NOT dispose the image. + */ + @Nullable + Image getImageByName(String imageName); + + /** + * Returns an image given its filename (with its extension). + * Might return null if the image cannot be loaded.
+ * @param imageName The filename (with extension) of the image to load. + * @return {@link ImageDescriptor} object or null if the image file is not found. + */ + @Nullable + ImageDescriptor getDescriptorByName(String imageName); + + /** + * Loads an image given its filename (with its extension), caches it using the given + * {@code KeyName} name and applies a filter to it. + * Might return null if the image cannot be loaded. + * The image is cached. Successive calls using {@code KeyName} will return the same + * object directly (the filter is not re-applied in this case.)
+ *

+ * @param imageName Filename (with extension) of the image to load. + * @param keyName Image key reference + * @param imageEditor Image editor + * @return {@link Image} or null if the image file is not found. The caller must NOT dispose the image. + */ + @Nullable + Image getImageByName(String imageName,String keyName, ImageEditor imageEditor); + + /** + * Loads an image given its filename (with its extension) and if not found, + * uses supplied {@code ReplacementImager} to create a replacement. + * Might return null if the image cannot be loaded. + * The image is cached. Successive calls using {@code KeyName} will return the same + * object directly
+ *

+ * @param imageName Filename (with extension) of the image to load. + * @param keyName Image key reference + * @param imageEditor Image editor + * @return {@link Image} or null if the image file is not found. The caller must NOT dispose the image. + */ + @Nullable + Image getImageByName(String imageName, ReplacementImager replacementImager); + + /** + * Returns image for given image file path + * @param imagePath A valid file system path relative to the bundle location eg. "icons/smile.gif" + * @return {@link Image} object or null if the image file is not found. The caller must NOT dispose the image + */ + Image getImage(String imagePath); + + /** + * Dispose all image resources + */ + void dispose(); + +} \ No newline at end of file diff --git a/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/JFaceImageLoader.java b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/JFaceImageLoader.java new file mode 100644 index 00000000..3c13a689 --- /dev/null +++ b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/JFaceImageLoader.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.base.resources; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.widgets.Display; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.utils.ILogger; + +public class JFaceImageLoader implements ImageFactory { + + /** Image file location when using {@link #getImageByName(String)} */ + public static String ICONS_PATH = "icons/"; + + protected Bundle bundle; + protected PluginResourceProvider provider; + protected final Map filterMap = new HashMap<>(); + protected ResourceManager resourceManager; + protected ILogger logger; + + /** + * Loads bundle images + * Images are loaded using a path relative to the bundle location. + * + * Instances are mangaged by a JFace resource manager, and thus should never be disposed by the image consumer. + * + */ + + /** + * Construct an ImageLoader object using given UI plugin instance. + * This object provides imageDescriptorFromPlugin() method + * @param bundle + */ + public JFaceImageLoader(@NonNull PluginResourceProvider provider) + { + this.provider = provider; + createResourceManager(); + } + + /** + * Construct an ImageLoader object using given bundle instance + * @param bundle + */ + public JFaceImageLoader(@NonNull Bundle bundle) + { + this.bundle = bundle; + createResourceManager(); + } + + /** + * Construct an ImageLoader object using given class of plugin associated with the bundle + * @param bundleClass + */ + public JFaceImageLoader(Class bundleClass) + { + this(FrameworkUtil.getBundle(bundleClass)); + } + + public void setLogger(ILogger logger) { + this.logger = logger; + } + + /* (non-Javadoc) + * @see org.eclipse.andmore.base.resources.ImageFactory#getImageByName(java.lang.String) + */ + @Override + @Nullable + public Image getImageByName(String imageName) { + return getImage(ICONS_PATH + imageName); + } + + + /* (non-Javadoc) + * @see org.eclipse.andmore.base.resources.ImageFactory#getImageByName(java.lang.String, java.lang.String, org.eclipse.andmore.base.resources.JFaceImageLoader.ImageEditor) + */ + @Override + @Nullable + public Image getImageByName(String imageName, + String keyName, + ImageEditor imageEditor) { + if (imageEditor == null) // No imageEditor means just load image. The keyName is irrelevant. + return getImageByName(imageName); + String imagePath = ICONS_PATH + imageName; + Image image = null; + ImageDescriptor imageDescriptor = descriptorFromPath(imagePath); + if (imageDescriptor != null) { + ImageDescriptor imagefilterDescriptor = filterMap.get(keyName); + if (imagefilterDescriptor == null) { + // Assume filter input = output + imagefilterDescriptor = imageDescriptor; + image = resourceManager.createImage(imageDescriptor); + ImageData imageData = imageEditor.edit(image); + if (imageData != null) { + // Create new image from data + imagefilterDescriptor = ImageDescriptor.createFromImageData(imageData); + image = resourceManager.createImage(imagefilterDescriptor); + } + filterMap.put(keyName, imagefilterDescriptor); + } + else + image = resourceManager.createImage(imagefilterDescriptor); + } + return image; + } + + /* (non-Javadoc) + * @see org.eclipse.andmore.base.resources.ImageFactory#getImage(java.lang.String) + */ + @Override + public Image getImage(String imagePath) { + Image image = null; + ImageDescriptor imageDescriptor = descriptorFromPath(imagePath); + if (imageDescriptor != null) { + image = resourceManager.createImage(imageDescriptor); + if ((image == null) && (logger != null)) + logger.error(null, "Image creation failed for image path " + imagePath); + } + return image; + } + + /* (non-Javadoc) + * @see org.eclipse.andmore.base.resources.ImageFactory#dispose() + */ + @Override + public void dispose() { + // Garbage collect system resources + if (resourceManager != null) + { + resourceManager.dispose(); + resourceManager = null; + } + } + + @Override + @Nullable + public Image getImageByName(String imageName, ReplacementImager replacementImager) { + String imagePath = ICONS_PATH + imageName; + ImageDescriptor imageDescriptor = descriptorFromPath(imagePath); + if (imageDescriptor == null) { + ImageDescriptor replacementImageDescriptor = filterMap.get(imagePath); + if (replacementImageDescriptor == null) { + replacementImageDescriptor = ImageDescriptor.createFromImageData(replacementImager.create()); + filterMap.put(imagePath, replacementImageDescriptor); + } + return resourceManager.createImage(replacementImageDescriptor); + } + return resourceManager.createImage(imageDescriptor); + } + + @Override + @Nullable + public ImageDescriptor getDescriptorByName(String imageName) { + String imagePath = ICONS_PATH + imageName; + return descriptorFromPath(imagePath); + } + + protected ImageDescriptor descriptorFromPath(String imagePath) { + if (provider != null) { + ImageDescriptor descriptor = provider.descriptorFromPath(imagePath); + if ((logger != null) && (descriptor == null)) + logger.error(null, "Image descriptor null for image path: " +imagePath); + return descriptor; + } + ImageDescriptor imageDescriptor = null; + // An image descriptor is an object that knows how to create an SWT image. + URL url = FileLocator.find(bundle, new Path(imagePath), null); + if (url != null) { + imageDescriptor = ImageDescriptor.createFromURL(url); + if (logger != null) { + if (imageDescriptor != null) + logger.info("Image file found at " + url.toString()); + else + logger.error(null, "Image descriptor null for URL: " + url.toString()); + } + } + else if (logger != null) + logger.error(null, "Image path not found: " + imagePath); + return imageDescriptor; + } + + /** + * Returns local Resource Manager + * @return ResourceManager object + */ + protected void createResourceManager() { + if (resourceManager == null) + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() + { + // getResources() returns the ResourceManager for the current display. + // May only be called from a UI thread. + resourceManager = new LocalResourceManager(JFaceResources.getResources()); + } + }); + } + + + +} diff --git a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/IPropertySource.java b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/PluginResourceProvider.java similarity index 68% rename from andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/IPropertySource.java rename to andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/PluginResourceProvider.java index 92bd6b93..9ca86fb4 100644 --- a/andmore-swt/org.eclipse.andmore.sdkuilib/src/main/java/com/android/sdklib/internal/project/IPropertySource.java +++ b/andmore-swt/org.eclipse.andmore.swt/src/org/eclipse/andmore/base/resources/PluginResourceProvider.java @@ -1,26 +1,22 @@ -/* - * Copyright (C) 2012 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.internal.project; - -/** - * A source able to return properties by name. - * - */ -public interface IPropertySource { - String getProperty(String name); - void debugPrint(); -} +/* + * Copyright (C) 2017 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 org.eclipse.andmore.base.resources; + +import org.eclipse.jface.resource.ImageDescriptor; + +public interface PluginResourceProvider { + ImageDescriptor descriptorFromPath(String imagePath); +} diff --git a/android-core/features/org.eclipse.andmore.package/feature.xml b/android-core/features/org.eclipse.andmore.package/feature.xml index edc5a300..bf96ac2f 100644 --- a/android-core/features/org.eclipse.andmore.package/feature.xml +++ b/android-core/features/org.eclipse.andmore.package/feature.xml @@ -1,46 +1,54 @@ - - - - - Android Developer Tools - - - - Copyright (C) 2007-2014 The Android Open Source Project - - - - %license - - - - - - - - - - - - - - - - - - - - - - + + + + + Android Developer Tools + + + + Copyright (C) 2007-2014 The Android Open Source Project + + + + %license + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-core/features/org.eclipse.andmore/feature.xml b/android-core/features/org.eclipse.andmore/feature.xml index 8d209d87..895806e3 100644 --- a/android-core/features/org.eclipse.andmore/feature.xml +++ b/android-core/features/org.eclipse.andmore/feature.xml @@ -1,120 +1,177 @@ - - - - - %feature.description - - - - %feature.copyright - - - - %license - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + %feature.description + + + + %feature.copyright + + + + %license + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.base/.classpath b/android-core/plugins/org.eclipse.andmore.base/.classpath index 62c0fbc5..7498423d 100644 --- a/android-core/plugins/org.eclipse.andmore.base/.classpath +++ b/android-core/plugins/org.eclipse.andmore.base/.classpath @@ -1,17 +1,7 @@ - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.base/.settings/org.eclipse.jdt.core.prefs b/android-core/plugins/org.eclipse.andmore.base/.settings/org.eclipse.jdt.core.prefs index ea661960..c137e176 100644 --- a/android-core/plugins/org.eclipse.andmore.base/.settings/org.eclipse.jdt.core.prefs +++ b/android-core/plugins/org.eclipse.andmore.base/.settings/org.eclipse.jdt.core.prefs @@ -1,98 +1,98 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled +org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/android-core/plugins/org.eclipse.andmore.base/META-INF/MANIFEST.MF b/android-core/plugins/org.eclipse.andmore.base/META-INF/MANIFEST.MF index ab73938d..831e9cb8 100644 --- a/android-core/plugins/org.eclipse.andmore.base/META-INF/MANIFEST.MF +++ b/android-core/plugins/org.eclipse.andmore.base/META-INF/MANIFEST.MF @@ -1,89 +1,17 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Common Android Utilities -Bundle-SymbolicName: org.eclipse.andmore.base;singleton:=true -Bundle-Version: 0.5.2.qualifier -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.apache.httpcomponents.httpclient;bundle-version="4.1.3", - org.apache.httpcomponents.httpcore;bundle-version="4.1.4", - org.apache.commons.logging;bundle-version="1.1.1", - org.apache.commons.codec;bundle-version="1.4.0", - org.apache.commons.compress;bundle-version="1.6.0", - com.google.gson;bundle-version="2.2.4" -Bundle-ActivationPolicy: lazy -Bundle-Vendor: Eclipse Andmore -Bundle-ClassPath: ., - libs/annotations.jar, - libs/common.jar, - libs/guava-17.0.jar, - libs/httpmime-4.1.jar, - libs/kxml2-2.3.0.jar, - libs/layoutlib-api.jar, - libs/sdklib.jar, - libs/sdkstats.jar, - libs/dvlib.jar, - libs/sdk-common.jar -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: com.android, - com.android.annotations, - com.android.annotations.concurrency, - com.android.dvlib, - com.android.ide.common.internal, - com.android.ide.common.packaging, - com.android.ide.common.rendering, - com.android.ide.common.rendering.api, - com.android.ide.common.rendering.legacy, - com.android.ide.common.res2, - com.android.ide.common.resources, - com.android.ide.common.resources.configuration, - com.android.ide.common.sdk, - com.android.ide.common.util, - com.android.ide.common.xml, - com.android.io, - com.android.layoutlib.api, - com.android.prefs, - com.android.resources, - com.android.sdklib, - com.android.sdklib.build, - com.android.sdklib.devices, - com.android.sdklib.internal.avd, - com.android.sdklib.internal.build, - com.android.sdklib.internal.project, - com.android.sdklib.internal.repository, - com.android.sdklib.internal.repository.archives, - com.android.sdklib.internal.repository.packages, - com.android.sdklib.internal.repository.sources, - com.android.sdklib.internal.repository.updater, - com.android.sdklib.io, - com.android.sdklib.repository, - com.android.sdklib.repository.descriptors, - com.android.sdklib.repository.local, - com.android.sdklib.util, - com.android.sdkstats, - com.android.util, - com.android.utils, - com.android.xml, - com.google.common.annotations, - com.google.common.base, - com.google.common.base.internal, - com.google.common.cache, - com.google.common.collect, - com.google.common.eventbus, - com.google.common.hash, - com.google.common.io, - com.google.common.math, - com.google.common.net, - com.google.common.primitives, - com.google.common.reflect, - com.google.common.util.concurrent, - org.apache.http.entity.mime, - org.apache.http.entity.mime.content, - org.eclipse.andmore.base, - org.kxml2.io, - org.kxml2.kdom, - org.kxml2.wap, - org.kxml2.wap.syncml, - org.kxml2.wap.wml, - org.kxml2.wap.wv, - org.xmlpull.v1 +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Common Android Utilities +Bundle-SymbolicName: org.eclipse.andmore.base;singleton:=true +Bundle-Version: 0.5.2.qualifier +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.apache.httpcomponents.httpclient;bundle-version="4.1.3", + org.apache.httpcomponents.httpcore;bundle-version="4.1.4", + org.apache.commons.logging;bundle-version="1.1.1", + org.apache.commons.codec;bundle-version="1.4.0", + org.apache.commons.compress;bundle-version="1.6.0", + com.google.gson;bundle-version="2.2.4" +Bundle-ActivationPolicy: lazy +Bundle-Vendor: Eclipse Andmore +Bundle-ClassPath: . +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/annotations.jar b/android-core/plugins/org.eclipse.andmore.base/libs/annotations.jar deleted file mode 100644 index 4010e30a..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/annotations.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/common.jar b/android-core/plugins/org.eclipse.andmore.base/libs/common.jar deleted file mode 100644 index bbcf3dde..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/common.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/dvlib.jar b/android-core/plugins/org.eclipse.andmore.base/libs/dvlib.jar deleted file mode 100644 index 842d87e3..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/dvlib.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/guava-17.0.jar b/android-core/plugins/org.eclipse.andmore.base/libs/guava-17.0.jar deleted file mode 100644 index 661fc747..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/guava-17.0.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/httpmime-4.1.jar b/android-core/plugins/org.eclipse.andmore.base/libs/httpmime-4.1.jar deleted file mode 100644 index 68f61584..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/httpmime-4.1.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/kxml2-2.3.0.jar b/android-core/plugins/org.eclipse.andmore.base/libs/kxml2-2.3.0.jar deleted file mode 100644 index 64709522..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/kxml2-2.3.0.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/layoutlib-api.jar b/android-core/plugins/org.eclipse.andmore.base/libs/layoutlib-api.jar deleted file mode 100644 index ae1d8245..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/layoutlib-api.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/sdk-common.jar b/android-core/plugins/org.eclipse.andmore.base/libs/sdk-common.jar deleted file mode 100644 index b041a023..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/sdk-common.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/sdklib.jar b/android-core/plugins/org.eclipse.andmore.base/libs/sdklib.jar deleted file mode 100644 index 4325ef6b..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/sdklib.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.base/libs/sdkstats.jar b/android-core/plugins/org.eclipse.andmore.base/libs/sdkstats.jar deleted file mode 100644 index 2b7fa9d0..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.base/libs/sdkstats.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/.classpath b/android-core/plugins/org.eclipse.andmore.ddms/.classpath index 5819809d..7498423d 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/.classpath +++ b/android-core/plugins/org.eclipse.andmore.ddms/.classpath @@ -1,10 +1,7 @@ - - - - - - - - - - + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.ddms/.settings/org.eclipse.jdt.core.prefs b/android-core/plugins/org.eclipse.andmore.ddms/.settings/org.eclipse.jdt.core.prefs index ea661960..c137e176 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/.settings/org.eclipse.jdt.core.prefs +++ b/android-core/plugins/org.eclipse.andmore.ddms/.settings/org.eclipse.jdt.core.prefs @@ -1,98 +1,98 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled +org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/android-core/plugins/org.eclipse.andmore.ddms/META-INF/MANIFEST.MF b/android-core/plugins/org.eclipse.andmore.ddms/META-INF/MANIFEST.MF index 16b45f39..31d7dddf 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/META-INF/MANIFEST.MF +++ b/android-core/plugins/org.eclipse.andmore.ddms/META-INF/MANIFEST.MF @@ -1,40 +1,24 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.andmore.ddms;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.ddms.DdmsPlugin -Bundle-Vendor: %Bundle-Vendor -Bundle-Localization: plugin -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.ui.console, - org.eclipse.core.resources, - org.eclipse.ui.ide, - org.eclipse.core.filesystem, - org.eclipse.andmore.base -Bundle-ActivationPolicy: lazy -Export-Package: com.android.ddmlib, - com.android.ddmlib.log, - com.android.ddmlib.testrunner, - com.android.ddmlib.utils, - com.android.ddmuilib, - com.android.ddmuilib.actions, - com.android.ddmuilib.annotation, - com.android.ddmuilib.console, - com.android.ddmuilib.explorer, - com.android.ddmuilib.handler, - com.android.ddmuilib.heap, - com.android.ddmuilib.location, - com.android.ddmuilib.log.event, - com.android.ddmuilib.logcat, - com.android.ddmuilib.net, - org.eclipse.andmore.ddms, - org.eclipse.andmore.ddms.i18n, - org.eclipse.andmore.ddms.preferences, - org.eclipse.andmore.ddms.views -Bundle-ClassPath: ., - libs/ddmlib.jar, - libs/ddmuilib.jar, - libs/uiautomatorviewer.jar -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.andmore.ddms;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.ddms.DdmsPlugin +Bundle-Vendor: %Bundle-Vendor +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ui.console, + org.eclipse.core.resources, + org.eclipse.ui.ide, + org.eclipse.core.filesystem, + org.eclipse.andmore.swt, + org.eclipse.andmore.ddmuilib, + org.eclipse.andmore.uiautomatorviewer +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.andmore.ddms, + org.eclipse.andmore.ddms.i18n, + org.eclipse.andmore.ddms.preferences, + org.eclipse.andmore.ddms.views +Bundle-ClassPath: . +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/android-core/plugins/org.eclipse.andmore.ddms/build.properties b/android-core/plugins/org.eclipse.andmore.ddms/build.properties index 3c02154c..8d833d5e 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/build.properties +++ b/android-core/plugins/org.eclipse.andmore.ddms/build.properties @@ -1,13 +1,15 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - icons/,\ - plugin.xml,\ - .,\ - libs/,\ - schema/,\ - about.html,\ - about.ini,\ - about.properties,\ - plugin.properties - +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + icons/,\ + plugin.xml,\ + .,\ + libs/,\ + schema/,\ + about.html,\ + about.ini,\ + about.properties,\ + plugin.properties,\ + ddm/icons/,\ + sdk/ + diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/add.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/add.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/add.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/add.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/android.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/android.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/android.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/android.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/backward.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/backward.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/backward.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/backward.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/capture.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/capture.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/capture.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/capture.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/clear.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/clear.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/clear.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/clear.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/d.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/d.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/d.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/d.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-attach.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-attach.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-attach.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-attach.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-error.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-error.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-error.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-error.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-wait.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-wait.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/debug-wait.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/debug-wait.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/delete.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/delete.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/delete.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/delete.png diff --git a/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/device.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/device.png new file mode 100644 index 00000000..7dbbbb6a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/device.png differ diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/diff.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/diff.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/diff.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/diff.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/displayfilters.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/displayfilters.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/displayfilters.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/displayfilters.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/down.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/down.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/down.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/down.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/e.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/e.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/e.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/e.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/edit.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/edit.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/edit.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/edit.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/empty.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/empty.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/empty.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/empty.png diff --git a/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/emulator.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/emulator.png new file mode 100644 index 00000000..a7180428 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/emulator.png differ diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/file.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/file.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/file.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/file.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/folder.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/folder.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/folder.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/folder.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/forward.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/forward.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/forward.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/forward.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/gc.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/gc.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/gc.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/gc.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/groupby.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/groupby.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/groupby.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/groupby.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/halt.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/halt.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/halt.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/halt.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/heap.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/heap.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/heap.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/heap.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/hprof.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/hprof.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/hprof.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/hprof.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/i.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/i.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/i.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/i.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/importBug.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/importBug.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/importBug.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/importBug.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/load.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/load.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/load.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/load.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/pause.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/pause.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/pause.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/pause.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/play.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/play.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/play.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/play.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/pull.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/pull.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/pull.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/pull.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/push.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/push.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/push.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/push.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/save.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/save.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/save.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/save.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/scroll_lock.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/scroll_lock.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/scroll_lock.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/scroll_lock.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/sort_down.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/sort_down.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/sort_down.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/sort_down.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/sort_up.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/sort_up.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/sort_up.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/sort_up.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/thread.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/thread.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/thread.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/thread.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/tracing_start.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/tracing_start.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/tracing_start.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/tracing_start.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/tracing_stop.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/tracing_stop.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/tracing_stop.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/tracing_stop.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/up.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/up.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/up.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/up.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/v.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/v.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/v.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/v.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/w.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/w.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/w.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/w.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/warning.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/warning.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/warning.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/warning.png diff --git a/andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/zygote.png b/android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/zygote.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.ddmuilib/src/main/java/images/zygote.png rename to android-core/plugins/org.eclipse.andmore.ddms/ddm/icons/zygote.png diff --git a/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmlib.jar b/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmlib.jar deleted file mode 100644 index ccc1f72f..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmlib.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmuilib.jar b/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmuilib.jar deleted file mode 100644 index 01e4079b..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.ddms/libs/ddmuilib.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/libs/uiautomatorviewer.jar b/android-core/plugins/org.eclipse.andmore.ddms/libs/uiautomatorviewer.jar deleted file mode 100644 index ebef827d..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.ddms/libs/uiautomatorviewer.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/accept_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/accept_icon16.png new file mode 100644 index 00000000..ae61f7df Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/accept_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/addon_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/addon_pkg_16.png new file mode 100644 index 00000000..addef8ef Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/addon_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_128.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_128.png new file mode 100644 index 00000000..830c04b0 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_128.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_16.png new file mode 100644 index 00000000..08ffda85 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/android_icon_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/archive_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/archive_icon16.png new file mode 100644 index 00000000..be5edd79 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/archive_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_16.png new file mode 100644 index 00000000..945d871b Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_pkg_16.png new file mode 100644 index 00000000..6daa67b8 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/broken_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/buildtool_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/buildtool_pkg_16.png new file mode 100644 index 00000000..9b917da4 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/buildtool_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/device.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/device.png new file mode 100644 index 00000000..7dbbbb6a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/device.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/doc_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/doc_pkg_16.png new file mode 100644 index 00000000..a2be37af Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/doc_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/emulator.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/emulator.png new file mode 100644 index 00000000..a7180428 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/emulator.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/error_icon_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/error_icon_16.png new file mode 100644 index 00000000..ccb4d0aa Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/error_icon_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/extra_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/extra_pkg_16.png new file mode 100644 index 00000000..7ad8a669 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/extra_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/incompat_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/incompat_icon16.png new file mode 100644 index 00000000..2a307e92 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/incompat_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_off_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_off_16.png new file mode 100644 index 00000000..ad2edff6 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_off_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_on_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_on_16.png new file mode 100644 index 00000000..ed27b520 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/log_on_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/nopkg_icon_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/nopkg_icon_16.png new file mode 100644 index 00000000..147837fd Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/nopkg_icon_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_incompat_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_incompat_16.png new file mode 100644 index 00000000..d7d3ae6e Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_incompat_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_installed_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_installed_16.png new file mode 100644 index 00000000..70295655 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_installed_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_new_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_new_16.png new file mode 100644 index 00000000..9c93afc8 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_new_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_update_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_update_16.png new file mode 100644 index 00000000..4171ba63 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkg_update_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_16.png new file mode 100644 index 00000000..0ee32bf8 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_other_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_other_16.png new file mode 100644 index 00000000..395a2403 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/pkgcat_other_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platform_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platform_pkg_16.png new file mode 100644 index 00000000..56e10d0a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platform_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platformtool_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platformtool_pkg_16.png new file mode 100644 index 00000000..424fb295 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/platformtool_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/reject_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/reject_icon16.png new file mode 100644 index 00000000..18c14811 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/reject_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sample_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sample_pkg_16.png new file mode 100644 index 00000000..11210bae Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sample_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sdkman_logo_128.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sdkman_logo_128.png new file mode 100644 index 00000000..0f1670d7 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sdkman_logo_128.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/source_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/source_pkg_16.png new file mode 100644 index 00000000..ab08d29a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/source_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/status_ok_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/status_ok_16.png new file mode 100644 index 00000000..ae61f7df Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/status_ok_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_disabled_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_disabled_16.png new file mode 100644 index 00000000..721d1841 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_disabled_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_enabled_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_enabled_16.png new file mode 100644 index 00000000..198f2998 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/stop_enabled_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sysimg_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sysimg_pkg_16.png new file mode 100644 index 00000000..942ce47a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/sysimg_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_16.png new file mode 100644 index 00000000..8887bcd3 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_32.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_32.png new file mode 100644 index 00000000..13fed144 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-tv_32.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_16.png new file mode 100644 index 00000000..652c5efa Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_32.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_32.png new file mode 100644 index 00000000..33560163 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_android-wear_32.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_16.png new file mode 100644 index 00000000..e3ad2e60 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_32.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_32.png new file mode 100644 index 00000000..f4264e7b Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tag_default_32.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tool_pkg_16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tool_pkg_16.png new file mode 100644 index 00000000..424fb295 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/tool_pkg_16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/unknown_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/unknown_icon16.png new file mode 100644 index 00000000..2b255fa9 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/unknown_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/warning_icon16.png b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/warning_icon16.png new file mode 100644 index 00000000..a2fcf7cf Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.ddms/sdk/icons/warning_icon16.png differ diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmResourceProvider.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmResourceProvider.java new file mode 100644 index 00000000..2ad96795 --- /dev/null +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmResourceProvider.java @@ -0,0 +1,13 @@ +package org.eclipse.andmore.ddms; + +import org.eclipse.andmore.base.resources.PluginResourceProvider; +import org.eclipse.jface.resource.ImageDescriptor; + +public class DdmResourceProvider implements PluginResourceProvider { + + @Override + public ImageDescriptor descriptorFromPath(String imagePath) { + return DdmsPlugin.getImageDescriptor("ddm/" + imagePath); + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmsPlugin.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmsPlugin.java index 0905eefc..ff00cc7b 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmsPlugin.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/DdmsPlugin.java @@ -1,924 +1,935 @@ -/* - * 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 org.eclipse.andmore.ddms; - -import com.android.annotations.NonNull; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.DdmPreferences; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.Log; -import com.android.ddmlib.Log.ILogOutput; -import com.android.ddmlib.Log.LogLevel; -import com.android.ddmuilib.DdmUiPreferences; -import com.android.ddmuilib.DevicePanel.IUiSelectionListener; -import com.android.ddmuilib.StackTracePanel; -import com.android.ddmuilib.console.DdmConsole; -import com.android.ddmuilib.console.IDdmConsole; - -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtensionPoint; -import org.eclipse.core.runtime.IExtensionRegistry; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.util.IPropertyChangeListener; -import org.eclipse.jface.util.PropertyChangeEvent; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.console.ConsolePlugin; -import org.eclipse.ui.console.IConsole; -import org.eclipse.ui.console.MessageConsole; -import org.eclipse.ui.console.MessageConsoleStream; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -import java.io.File; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; - -/** - * The activator class controls the plug-in life cycle - */ -public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener, IUiSelectionListener, - com.android.ddmuilib.StackTracePanel.ISourceRevealer { - - // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.andmore.ddms"; //$NON-NLS-1$ - - public static final String NEWLINE = System.getProperty("line.separator"); - - /** The singleton instance */ - private static DdmsPlugin sPlugin; - - /** Location of the adb command line executable */ - private static String sAdbLocation; - private static String sToolsFolder; - private static String sHprofConverter; - - private boolean mHasDebuggerConnectors; - /** - * debugger connectors for already running apps. Initialized from an - * extension point. - */ - private IDebuggerConnector[] mDebuggerConnectors; - private ITraceviewLauncher[] mTraceviewLaunchers; - private List mClientSpecificActions = null; - - /** Console for DDMS log message */ - private MessageConsole mDdmsConsole; - - private IDevice mCurrentDevice; - private Client mCurrentClient; - private boolean mListeningToUiSelection = false; - - private final ArrayList mListeners = new ArrayList(); - - private Color mRed; - - /** - * Classes which implement this interface provide methods that deals with - * {@link IDevice} and {@link Client} selectionchanges. - */ - public interface ISelectionListener { - - /** - * Sent when a new {@link Client} is selected. - * - * @param selectedClient - * The selected client. If null, no clients are selected. - */ - public void selectionChanged(Client selectedClient); - - /** - * Sent when a new {@link IDevice} is selected. - * - * @param selectedDevice - * the selected device. If null, no devices are selected. - */ - public void selectionChanged(IDevice selectedDevice); - } - - /** - * The constructor - */ - public DdmsPlugin() { - sPlugin = this; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext - * ) - */ - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - - final Display display = getDisplay(); - - // get the eclipse store - final IPreferenceStore eclipseStore = getPreferenceStore(); - - AndroidDebugBridge.addDeviceChangeListener(this); - - DdmUiPreferences.setStore(eclipseStore); - - // DdmUiPreferences.displayCharts(); - - // set the consoles. - mDdmsConsole = new MessageConsole("DDMS", null); //$NON-NLS-1$ - ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { mDdmsConsole }); - - final MessageConsoleStream consoleStream = mDdmsConsole.newMessageStream(); - final MessageConsoleStream errorConsoleStream = mDdmsConsole.newMessageStream(); - mRed = new Color(display, 0xFF, 0x00, 0x00); - - // because this can be run, in some cases, by a non UI thread, and - // because - // changing the console properties update the UI, we need to make this - // change - // in the UI thread. - display.asyncExec(new Runnable() { - @Override - public void run() { - errorConsoleStream.setColor(mRed); - } - }); - - // set up the ddms log to use the ddms console. - Log.setLogOutput(new ILogOutput() { - @Override - public void printLog(LogLevel logLevel, String tag, String message) { - if (logLevel.getPriority() >= LogLevel.ERROR.getPriority()) { - printToStream(errorConsoleStream, tag, message); - showConsoleView(mDdmsConsole); - } else { - printToStream(consoleStream, tag, message); - } - } - - @Override - public void printAndPromptLog(final LogLevel logLevel, final String tag, final String message) { - printLog(logLevel, tag, message); - // dialog box only run in UI thread.. - display.asyncExec(new Runnable() { - @Override - public void run() { - Shell shell = display.getActiveShell(); - if (logLevel == LogLevel.ERROR) { - MessageDialog.openError(shell, tag, message); - } else { - MessageDialog.openWarning(shell, tag, message); - } - } - }); - } - - }); - - // set up the ddms console to use this objects - DdmConsole.setConsole(new IDdmConsole() { - @Override - public void printErrorToConsole(String message) { - printToStream(errorConsoleStream, null, message); - showConsoleView(mDdmsConsole); - } - - @Override - public void printErrorToConsole(String[] messages) { - for (String m : messages) { - printToStream(errorConsoleStream, null, m); - } - showConsoleView(mDdmsConsole); - } - - @Override - public void printToConsole(String message) { - printToStream(consoleStream, null, message); - } - - @Override - public void printToConsole(String[] messages) { - for (String m : messages) { - printToStream(consoleStream, null, m); - } - } - }); - - // set the listener for the preference change - eclipseStore.addPropertyChangeListener(new IPropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent event) { - // get the name of the property that changed. - String property = event.getProperty(); - - if (PreferenceInitializer.ATTR_DEBUG_PORT_BASE.equals(property)) { - DdmPreferences.setDebugPortBase(eclipseStore.getInt(PreferenceInitializer.ATTR_DEBUG_PORT_BASE)); - } else if (PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT.equals(property)) { - DdmPreferences.setSelectedDebugPort(eclipseStore - .getInt(PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT)); - } else if (PreferenceInitializer.ATTR_THREAD_INTERVAL.equals(property)) { - DdmUiPreferences.setThreadRefreshInterval(eclipseStore - .getInt(PreferenceInitializer.ATTR_THREAD_INTERVAL)); - } else if (PreferenceInitializer.ATTR_LOG_LEVEL.equals(property)) { - DdmPreferences.setLogLevel(eclipseStore.getString(PreferenceInitializer.ATTR_LOG_LEVEL)); - } else if (PreferenceInitializer.ATTR_TIME_OUT.equals(property)) { - DdmPreferences.setTimeOut(eclipseStore.getInt(PreferenceInitializer.ATTR_TIME_OUT)); - } else if (PreferenceInitializer.ATTR_USE_ADBHOST.equals(property)) { - DdmPreferences.setUseAdbHost(eclipseStore.getBoolean(PreferenceInitializer.ATTR_USE_ADBHOST)); - } else if (PreferenceInitializer.ATTR_ADBHOST_VALUE.equals(property)) { - DdmPreferences.setAdbHostValue(eclipseStore.getString(PreferenceInitializer.ATTR_ADBHOST_VALUE)); - } - } - }); - - // do some last initializations - - // set the preferences. - PreferenceInitializer.setupPreferences(); - - // this class is set as the main source revealer and will look at all - // the implementations - // of the extension point. see #reveal(String, String, int) - StackTracePanel.setSourceRevealer(this); - - /* - * Load the extension point implementations. The first step is to load - * the IConfigurationElement representing the implementations. The 2nd - * step is to use these objects to instantiate the implementation - * classes. - * - * Because the 2nd step will trigger loading the plug-ins providing the - * implementations, and those plug-ins could access DDMS classes (like - * ADT), this 2nd step should be done in a Job to ensure that DDMS is - * loaded, so that the other plug-ins can load. - * - * Both steps could be done in the 2nd step but some of DDMS UI rely on - * knowing if there is an implementation or not (DeviceView), so we do - * the first steps in start() and, in some case, record it. - */ - - // get the IConfigurationElement for the debuggerConnector right away. - final IConfigurationElement[] dcce = findConfigElements("org.eclipse.andmore.ddms.debuggerConnector"); //$NON-NLS-1$ - mHasDebuggerConnectors = dcce.length > 0; - - // get the other configElements and instantiante them in a Job. - new Job(Messages.DdmsPlugin_DDMS_Post_Create_Init) { - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - // init the lib - AndroidDebugBridge.init(true /* debugger support */); - - // get the available adb locators - IConfigurationElement[] elements = findConfigElements("org.eclipse.andmore.ddms.toolsLocator"); //$NON-NLS-1$ - - IToolsLocator[] locators = instantiateToolsLocators(elements); - - for (IToolsLocator locator : locators) { - try { - String adbLocation = locator.getAdbLocation(); - String traceviewLocation = locator.getTraceViewLocation(); - String hprofConvLocation = locator.getHprofConvLocation(); - if (adbLocation != null && traceviewLocation != null && hprofConvLocation != null) { - // checks if the location is valid. - if (setToolsLocation(adbLocation, hprofConvLocation, traceviewLocation)) { - - AndroidDebugBridge.createBridge(sAdbLocation, true /* forceNewBridge */); - - // no need to look at the other locators. - break; - } - } - } catch (Throwable t) { - // ignore, we'll just not use this implementation. - } - } - - // get the available debugger connectors - mDebuggerConnectors = instantiateDebuggerConnectors(dcce); - - // get the available Traceview Launchers. - elements = findConfigElements("org.eclipse.andmore.ddms.traceviewLauncher"); //$NON-NLS-1$ - mTraceviewLaunchers = instantiateTraceviewLauncher(elements); - - return Status.OK_STATUS; - } catch (CoreException e) { - return e.getStatus(); - } - } - }.schedule(); - } - - private void showConsoleView(MessageConsole console) { - ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console); - } - - /** - * Obtain a list of configuration elements that extend the given extension - * point. - */ - IConfigurationElement[] findConfigElements(String extensionPointId) { - // get the adb location from an implementation of the ADB Locator - // extension point. - IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); - IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(extensionPointId); - if (extensionPoint != null) { - return extensionPoint.getConfigurationElements(); - } - - // shouldn't happen or it means the plug-in is broken. - return new IConfigurationElement[0]; - } - - /** - * Finds if any other plug-in is extending the exposed Extension Point - * called adbLocator. - * - * @return an array of all locators found, or an empty array if none were - * found. - */ - private IToolsLocator[] instantiateToolsLocators(IConfigurationElement[] configElements) throws CoreException { - ArrayList list = new ArrayList(); - - if (configElements.length > 0) { - // only use the first one, ignore the others. - IConfigurationElement configElement = configElements[0]; - - // instantiate the class - Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ - if (obj instanceof IToolsLocator) { - list.add((IToolsLocator) obj); - } - } - - return list.toArray(new IToolsLocator[list.size()]); - } - - /** - * Finds if any other plug-in is extending the exposed Extension Point - * called debuggerConnector. - * - * @return an array of all locators found, or an empty array if none were - * found. - */ - private IDebuggerConnector[] instantiateDebuggerConnectors(IConfigurationElement[] configElements) - throws CoreException { - ArrayList list = new ArrayList(); - - if (configElements.length > 0) { - // only use the first one, ignore the others. - IConfigurationElement configElement = configElements[0]; - - // instantiate the class - Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ - if (obj instanceof IDebuggerConnector) { - list.add((IDebuggerConnector) obj); - } - } - - return list.toArray(new IDebuggerConnector[list.size()]); - } - - /** - * Finds if any other plug-in is extending the exposed Extension Point - * called traceviewLauncher. - * - * @return an array of all locators found, or an empty array if none were - * found. - */ - private ITraceviewLauncher[] instantiateTraceviewLauncher(IConfigurationElement[] configElements) - throws CoreException { - ArrayList list = new ArrayList(); - - if (configElements.length > 0) { - // only use the first one, ignore the others. - IConfigurationElement configElement = configElements[0]; - - // instantiate the class - Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ - if (obj instanceof ITraceviewLauncher) { - list.add((ITraceviewLauncher) obj); - } - } - - return list.toArray(new ITraceviewLauncher[list.size()]); - } - - /** - * Returns the classes that implement {@link IClientAction} in each of the - * extensions that extend clientAction extension point. - * - * @throws CoreException - */ - private List instantiateClientSpecificActions(IConfigurationElement[] elements) throws CoreException { - if (elements == null || elements.length == 0) { - return Collections.emptyList(); - } - - List extensions = new ArrayList(1); - - for (IConfigurationElement e : elements) { - Object o = e.createExecutableExtension("class"); //$NON-NLS-1$ - if (o instanceof IClientAction) { - extensions.add((IClientAction) o); - } - } - - return extensions; - } - - public static Display getDisplay() { - IWorkbench bench = sPlugin.getWorkbench(); - if (bench != null) { - return bench.getDisplay(); - } - return null; - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext - * ) - */ - @Override - public void stop(BundleContext context) throws Exception { - AndroidDebugBridge.removeDeviceChangeListener(this); - - AndroidDebugBridge.terminate(); - - mRed.dispose(); - - sPlugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static DdmsPlugin getDefault() { - return sPlugin; - } - - public static String getAdb() { - return sAdbLocation; - } - - public static File getPlatformToolsFolder() { - return new File(sAdbLocation).getParentFile(); - } - - public static String getToolsFolder() { - return sToolsFolder; - } - - public static String getHprofConverter() { - return sHprofConverter; - } - - /** - * Stores the adb location. This returns true if the location is an existing - * file. - */ - private static boolean setToolsLocation(String adbLocation, String hprofConvLocation, String traceViewLocation) { - - File adb = new File(adbLocation); - File hprofConverter = new File(hprofConvLocation); - File traceview = new File(traceViewLocation); - - String missing = ""; - if (adb.isFile() == false) { - missing += adb.getAbsolutePath() + " "; - } - if (hprofConverter.isFile() == false) { - missing += hprofConverter.getAbsolutePath() + " "; - } - if (traceview.isFile() == false) { - missing += traceview.getAbsolutePath() + " "; - } - - if (missing.length() > 0) { - String msg = String.format("DDMS files not found: %1$s", missing); - Log.e("DDMS", msg); - Status status = new Status(IStatus.ERROR, PLUGIN_ID, msg, null /* exception */); - getDefault().getLog().log(status); - return false; - } - - sAdbLocation = adbLocation; - sHprofConverter = hprofConverter.getAbsolutePath(); - DdmUiPreferences.setTraceviewLocation(traceview.getAbsolutePath()); - - sToolsFolder = traceview.getParent(); - - return true; - } - - /** - * Set the location of the adb executable and optionally starts adb - * - * @param adb - * location of adb - * @param startAdb - * flag to start adb - */ - public static void setToolsLocation(String adbLocation, boolean startAdb, String hprofConvLocation, - String traceViewLocation) { - - if (setToolsLocation(adbLocation, hprofConvLocation, traceViewLocation)) { - // starts the server in a thread in case this is blocking. - if (startAdb) { - new Thread() { - @Override - public void run() { - // create and start the bridge - try { - AndroidDebugBridge.createBridge(sAdbLocation, false /* forceNewBridge */); - } catch (Throwable t) { - Status status = new Status(IStatus.ERROR, PLUGIN_ID, "Failed to create AndroidDebugBridge", - t); - getDefault().getLog().log(status); - } - } - }.start(); - } - } - } - - /** - * Returns whether there are implementations of the debuggerConnectors - * extension point. - *

- * This is guaranteed to return the correct value as soon as the plug-in is - * loaded. - */ - public boolean hasDebuggerConnectors() { - return mHasDebuggerConnectors; - } - - /** - * Returns the implementations of {@link IDebuggerConnector}. - *

- * There may be a small amount of time right after the plug-in load where - * this can return null even if there are implementation. - *

- * Since the use of the implementation likely require user input, the UI can - * use {@link #hasDebuggerConnectors()} to know if there are implementations - * before they are loaded. - */ - public IDebuggerConnector[] getDebuggerConnectors() { - return mDebuggerConnectors; - } - - public synchronized void addSelectionListener(ISelectionListener listener) { - mListeners.add(listener); - - // notify the new listener of the current selection - listener.selectionChanged(mCurrentDevice); - listener.selectionChanged(mCurrentClient); - } - - public synchronized void removeSelectionListener(ISelectionListener listener) { - mListeners.remove(listener); - } - - public synchronized void setListeningState(boolean state) { - mListeningToUiSelection = state; - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - *

- * This is sent from a non UI thread. - * - * @param device - * the new device. - * - * @see IDeviceChangeListener#deviceConnected(IDevice) - */ - @Override - public void deviceConnected(IDevice device) { - // if we are listening to selection coming from the ui, then we do - // nothing, as - // any change in the devices/clients, will be handled by the UI, and - // we'll receive - // selection notification through our implementation of - // IUiSelectionListener. - if (mListeningToUiSelection == false) { - if (mCurrentDevice == null) { - handleDefaultSelection(device); - } - } - } - - /** - * Sent when the a device is disconnected to the {@link AndroidDebugBridge}. - *

- * This is sent from a non UI thread. - * - * @param device - * the new device. - * - * @see IDeviceChangeListener#deviceDisconnected(IDevice) - */ - @Override - public void deviceDisconnected(IDevice device) { - // if we are listening to selection coming from the ui, then we do - // nothing, as - // any change in the devices/clients, will be handled by the UI, and - // we'll receive - // selection notification through our implementation of - // IUiSelectionListener. - if (mListeningToUiSelection == false) { - // test if the disconnected device was the default selection. - if (mCurrentDevice == device) { - // try to find a new device - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - if (bridge != null) { - // get the device list - IDevice[] devices = bridge.getDevices(); - - // check if we still have devices - if (devices.length == 0) { - handleDefaultSelection((IDevice) null); - } else { - handleDefaultSelection(devices[0]); - } - } else { - handleDefaultSelection((IDevice) null); - } - } - } - } - - /** - * Sent when a device data changed, or when clients are started/terminated - * on the device. - *

- * This is sent from a non UI thread. - * - * @param device - * the device that was updated. - * @param changeMask - * the mask indicating what changed. - * - * @see IDeviceChangeListener#deviceChanged(IDevice) - */ - @Override - public void deviceChanged(IDevice device, int changeMask) { - // if we are listening to selection coming from the ui, then we do - // nothing, as - // any change in the devices/clients, will be handled by the UI, and - // we'll receive - // selection notification through our implementation of - // IUiSelectionListener. - if (mListeningToUiSelection == false) { - - // check if this is our device - if (device == mCurrentDevice) { - if (mCurrentClient == null) { - handleDefaultSelection(device); - } else { - // get the clients and make sure ours is still in there. - Client[] clients = device.getClients(); - boolean foundClient = false; - for (Client client : clients) { - if (client == mCurrentClient) { - foundClient = true; - break; - } - } - - // if we haven't found our client, lets look for a new one - if (foundClient == false) { - mCurrentClient = null; - handleDefaultSelection(device); - } - } - } - } - } - - /** - * Sent when a new {@link IDevice} and {@link Client} are selected. - * - * @param selectedDevice - * the selected device. If null, no devices are selected. - * @param selectedClient - * The selected client. If null, no clients are selected. - */ - @Override - public synchronized void selectionChanged(IDevice selectedDevice, Client selectedClient) { - if (mCurrentDevice != selectedDevice) { - mCurrentDevice = selectedDevice; - - // notify of the new default device - for (ISelectionListener listener : mListeners) { - listener.selectionChanged(mCurrentDevice); - } - } - - if (mCurrentClient != selectedClient) { - mCurrentClient = selectedClient; - - // notify of the new default client - for (ISelectionListener listener : mListeners) { - listener.selectionChanged(mCurrentClient); - } - } - } - - /** - * Handles a default selection of a {@link IDevice} and {@link Client}. - * - * @param device - * the selected device - */ - private void handleDefaultSelection(final IDevice device) { - // because the listener expect to receive this from the UI thread, and - // this is called - // from the AndroidDebugBridge notifications, we need to run this in the - // UI thread. - try { - Display display = getDisplay(); - - display.asyncExec(new Runnable() { - @Override - public void run() { - // set the new device if different. - boolean newDevice = false; - if (mCurrentDevice != device) { - mCurrentDevice = device; - newDevice = true; - - // notify of the new default device - for (ISelectionListener listener : mListeners) { - listener.selectionChanged(mCurrentDevice); - } - } - - if (device != null) { - // if this is a device switch or the same device but we - // didn't find a valid - // client the last time, we go look for a client to use - // again. - if (newDevice || mCurrentClient == null) { - // now get the new client - Client[] clients = device.getClients(); - if (clients.length > 0) { - handleDefaultSelection(clients[0]); - } else { - handleDefaultSelection((Client) null); - } - } - } else { - handleDefaultSelection((Client) null); - } - } - }); - } catch (SWTException e) { - // display is disposed. Do nothing since we're quitting anyway. - } - } - - private void handleDefaultSelection(Client client) { - mCurrentClient = client; - - // notify of the new default client - for (ISelectionListener listener : mListeners) { - listener.selectionChanged(mCurrentClient); - } - } - - /** - * Prints a message, associated with a project to the specified stream - * - * @param stream - * The stream to write to - * @param tag - * The tag associated to the message. Can be null - * @param message - * The message to print. - */ - private static synchronized void printToStream(MessageConsoleStream stream, String tag, String message) { - String dateTag = getMessageTag(tag); - - stream.print(dateTag); - if (!dateTag.endsWith(" ")) { - stream.print(" "); //$NON-NLS-1$ - } - stream.println(message); - } - - /** - * Creates a string containing the current date/time, and the tag - * - * @param tag - * The tag associated to the message. Can be null - * @return The dateTag - */ - private static String getMessageTag(String tag) { - Calendar c = Calendar.getInstance(); - - if (tag == null) { - return String.format(Messages.DdmsPlugin_Message_Tag_Mask_1, c); - } - - return String.format(Messages.DdmsPlugin_Message_Tag_Mask_2, c, tag); - } - - /** - * Implementation of com.android.ddmuilib.StackTracePanel.ISourceRevealer. - */ - @Override - public void reveal(String applicationName, String className, int line) { - JavaSourceRevealer.reveal(applicationName, className, line); - } - - public boolean launchTraceview(String osPath) { - if (mTraceviewLaunchers != null) { - for (ITraceviewLauncher launcher : mTraceviewLaunchers) { - try { - if (launcher.openFile(osPath)) { - return true; - } - } catch (Throwable t) { - // ignore, we'll just not use this implementation. - } - } - } - - return false; - } - - /** - * Returns the list of clients that extend the clientAction extension point. - */ - @NonNull - public synchronized List getClientSpecificActions() { - if (mClientSpecificActions == null) { - // get available client specific action extensions - IConfigurationElement[] elements = findConfigElements("org.eclipse.andmore.ddms.clientAction"); //$NON-NLS-1$ - try { - mClientSpecificActions = instantiateClientSpecificActions(elements); - } catch (CoreException e) { - mClientSpecificActions = Collections.emptyList(); - } - } - - return mClientSpecificActions; - } - - private LogCatMonitor mLogCatMonitor; - - public void startLogCatMonitor(IDevice device) { - if (mLogCatMonitor == null) { - mLogCatMonitor = new LogCatMonitor(getDebuggerConnectors(), getPreferenceStore()); - } - - mLogCatMonitor.monitorDevice(device); - } - - /** - * Returns an image descriptor for the image file at the given plug-in - * relative path - */ - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } -} +/* + * 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 org.eclipse.andmore.ddms; + +import com.android.annotations.NonNull; +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; +import com.android.ddmlib.Client; +import com.android.ddmlib.DdmPreferences; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.Log; +import com.android.ddmlib.Log.ILogOutput; +import com.android.ddmlib.Log.LogLevel; +import com.android.ddmuilib.DdmUiPreferences; +import com.android.ddmuilib.DevicePanel.IUiSelectionListener; +import com.android.ddmuilib.StackTracePanel; +import com.android.ddmuilib.console.DdmConsole; +import com.android.ddmuilib.console.IDdmConsole; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.base.resources.JFaceImageLoader; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.MessageConsole; +import org.eclipse.ui.console.MessageConsoleStream; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + +/** + * The activator class controls the plug-in life cycle + */ +public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener, IUiSelectionListener, + com.android.ddmuilib.StackTracePanel.ISourceRevealer { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.andmore.ddms"; //$NON-NLS-1$ + + public static final String NEWLINE = System.getProperty("line.separator"); + + /** The singleton instance */ + private static DdmsPlugin sPlugin; + + /** Location of the adb command line executable */ + private static String sAdbLocation; + private static String sToolsFolder; + private static String sHprofConverter; + + private boolean mHasDebuggerConnectors; + /** + * debugger connectors for already running apps. Initialized from an + * extension point. + */ + private IDebuggerConnector[] mDebuggerConnectors; + private ITraceviewLauncher[] mTraceviewLaunchers; + private List mClientSpecificActions = null; + + /** Console for DDMS log message */ + private MessageConsole mDdmsConsole; + + private IDevice mCurrentDevice; + private Client mCurrentClient; + private boolean mListeningToUiSelection = false; + + private final ArrayList mListeners = new ArrayList(); + + private Color mRed; + private ImageFactory mImageFactory; + + /** + * Classes which implement this interface provide methods that deals with + * {@link IDevice} and {@link Client} selectionchanges. + */ + public interface ISelectionListener { + + /** + * Sent when a new {@link Client} is selected. + * + * @param selectedClient + * The selected client. If null, no clients are selected. + */ + public void selectionChanged(Client selectedClient); + + /** + * Sent when a new {@link IDevice} is selected. + * + * @param selectedDevice + * the selected device. If null, no devices are selected. + */ + public void selectionChanged(IDevice selectedDevice); + } + + /** + * The constructor + */ + public DdmsPlugin() { + sPlugin = this; + } + + public ImageFactory getImageFactory() { + return mImageFactory; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + + final Display display = getDisplay(); + + // get the eclipse store + final IPreferenceStore eclipseStore = getPreferenceStore(); + + AndroidDebugBridge.addDeviceChangeListener(this); + + DdmUiPreferences.setStore(eclipseStore); + + // DdmUiPreferences.displayCharts(); + + // set the consoles. + mDdmsConsole = new MessageConsole("DDMS", null); //$NON-NLS-1$ + ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { mDdmsConsole }); + + final MessageConsoleStream consoleStream = mDdmsConsole.newMessageStream(); + final MessageConsoleStream errorConsoleStream = mDdmsConsole.newMessageStream(); + mRed = new Color(display, 0xFF, 0x00, 0x00); + + // because this can be run, in some cases, by a non UI thread, and + // because + // changing the console properties update the UI, we need to make this + // change + // in the UI thread. + display.asyncExec(new Runnable() { + @Override + public void run() { + errorConsoleStream.setColor(mRed); + } + }); + + // set up the ddms log to use the ddms console. + Log.addLogger(new ILogOutput() { + @Override + public void printLog(LogLevel logLevel, String tag, String message) { + if (logLevel.getPriority() >= LogLevel.ERROR.getPriority()) { + printToStream(errorConsoleStream, tag, message); + showConsoleView(mDdmsConsole); + } else { + printToStream(consoleStream, tag, message); + } + } + + @Override + public void printAndPromptLog(final LogLevel logLevel, final String tag, final String message) { + printLog(logLevel, tag, message); + // dialog box only run in UI thread.. + display.asyncExec(new Runnable() { + @Override + public void run() { + Shell shell = display.getActiveShell(); + if (logLevel == LogLevel.ERROR) { + MessageDialog.openError(shell, tag, message); + } else { + MessageDialog.openWarning(shell, tag, message); + } + } + }); + } + + }); + + // set up the ddms console to use this objects + DdmConsole.setConsole(new IDdmConsole() { + @Override + public void printErrorToConsole(String message) { + printToStream(errorConsoleStream, null, message); + showConsoleView(mDdmsConsole); + } + + @Override + public void printErrorToConsole(String[] messages) { + for (String m : messages) { + printToStream(errorConsoleStream, null, m); + } + showConsoleView(mDdmsConsole); + } + + @Override + public void printToConsole(String message) { + printToStream(consoleStream, null, message); + } + + @Override + public void printToConsole(String[] messages) { + for (String m : messages) { + printToStream(consoleStream, null, m); + } + } + }); + + // set the listener for the preference change + eclipseStore.addPropertyChangeListener(new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + // get the name of the property that changed. + String property = event.getProperty(); + + if (PreferenceInitializer.ATTR_DEBUG_PORT_BASE.equals(property)) { + DdmPreferences.setDebugPortBase(eclipseStore.getInt(PreferenceInitializer.ATTR_DEBUG_PORT_BASE)); + } else if (PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT.equals(property)) { + DdmPreferences.setSelectedDebugPort(eclipseStore + .getInt(PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT)); + } else if (PreferenceInitializer.ATTR_THREAD_INTERVAL.equals(property)) { + DdmUiPreferences.setThreadRefreshInterval(eclipseStore + .getInt(PreferenceInitializer.ATTR_THREAD_INTERVAL)); + } else if (PreferenceInitializer.ATTR_LOG_LEVEL.equals(property)) { + DdmPreferences.setLogLevel(eclipseStore.getString(PreferenceInitializer.ATTR_LOG_LEVEL)); + } else if (PreferenceInitializer.ATTR_TIME_OUT.equals(property)) { + DdmPreferences.setTimeOut(eclipseStore.getInt(PreferenceInitializer.ATTR_TIME_OUT)); + } else if (PreferenceInitializer.ATTR_USE_ADBHOST.equals(property)) { + DdmPreferences.setUseAdbHost(eclipseStore.getBoolean(PreferenceInitializer.ATTR_USE_ADBHOST)); + } else if (PreferenceInitializer.ATTR_ADBHOST_VALUE.equals(property)) { + DdmPreferences.setAdbHostValue(eclipseStore.getString(PreferenceInitializer.ATTR_ADBHOST_VALUE)); + } + } + }); + + // do some last initializations + + mImageFactory = new JFaceImageLoader(new DdmResourceProvider()); + // set the preferences. + PreferenceInitializer.setupPreferences(); + + // this class is set as the main source revealer and will look at all + // the implementations + // of the extension point. see #reveal(String, String, int) + StackTracePanel.setSourceRevealer(this); + + /* + * Load the extension point implementations. The first step is to load + * the IConfigurationElement representing the implementations. The 2nd + * step is to use these objects to instantiate the implementation + * classes. + * + * Because the 2nd step will trigger loading the plug-ins providing the + * implementations, and those plug-ins could access DDMS classes (like + * ADT), this 2nd step should be done in a Job to ensure that DDMS is + * loaded, so that the other plug-ins can load. + * + * Both steps could be done in the 2nd step but some of DDMS UI rely on + * knowing if there is an implementation or not (DeviceView), so we do + * the first steps in start() and, in some case, record it. + */ + + // get the IConfigurationElement for the debuggerConnector right away. + final IConfigurationElement[] dcce = findConfigElements("org.eclipse.andmore.ddms.debuggerConnector"); //$NON-NLS-1$ + mHasDebuggerConnectors = dcce.length > 0; + + // get the other configElements and instantiante them in a Job. + new Job(Messages.DdmsPlugin_DDMS_Post_Create_Init) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + // init the lib + AndroidDebugBridge.init(true /* debugger support */); + + // get the available adb locators + IConfigurationElement[] elements = findConfigElements("org.eclipse.andmore.ddms.toolsLocator"); //$NON-NLS-1$ + + IToolsLocator[] locators = instantiateToolsLocators(elements); + + for (IToolsLocator locator : locators) { + try { + String adbLocation = locator.getAdbLocation(); + String traceviewLocation = locator.getTraceViewLocation(); + String hprofConvLocation = locator.getHprofConvLocation(); + if (adbLocation != null && traceviewLocation != null && hprofConvLocation != null) { + // checks if the location is valid. + if (setToolsLocation(adbLocation, hprofConvLocation, traceviewLocation)) { + + AndroidDebugBridge.createBridge(sAdbLocation, true /* forceNewBridge */); + + // no need to look at the other locators. + break; + } + } + } catch (Throwable t) { + // ignore, we'll just not use this implementation. + } + } + + // get the available debugger connectors + mDebuggerConnectors = instantiateDebuggerConnectors(dcce); + + // get the available Traceview Launchers. + elements = findConfigElements("org.eclipse.andmore.ddms.traceviewLauncher"); //$NON-NLS-1$ + mTraceviewLaunchers = instantiateTraceviewLauncher(elements); + + return Status.OK_STATUS; + } catch (CoreException e) { + return e.getStatus(); + } + } + }.schedule(); + } + + private void showConsoleView(MessageConsole console) { + ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console); + } + + /** + * Obtain a list of configuration elements that extend the given extension + * point. + */ + IConfigurationElement[] findConfigElements(String extensionPointId) { + // get the adb location from an implementation of the ADB Locator + // extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + // NPE occurred during testing + if (extensionRegistry != null) + { + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(extensionPointId); + if (extensionPoint != null) { + return extensionPoint.getConfigurationElements(); + } + } + // shouldn't happen or it means the plug-in is broken. + return new IConfigurationElement[0]; + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point + * called adbLocator. + * + * @return an array of all locators found, or an empty array if none were + * found. + */ + private IToolsLocator[] instantiateToolsLocators(IConfigurationElement[] configElements) throws CoreException { + ArrayList list = new ArrayList(); + + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the class + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IToolsLocator) { + list.add((IToolsLocator) obj); + } + } + + return list.toArray(new IToolsLocator[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point + * called debuggerConnector. + * + * @return an array of all locators found, or an empty array if none were + * found. + */ + private IDebuggerConnector[] instantiateDebuggerConnectors(IConfigurationElement[] configElements) + throws CoreException { + ArrayList list = new ArrayList(); + + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the class + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IDebuggerConnector) { + list.add((IDebuggerConnector) obj); + } + } + + return list.toArray(new IDebuggerConnector[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point + * called traceviewLauncher. + * + * @return an array of all locators found, or an empty array if none were + * found. + */ + private ITraceviewLauncher[] instantiateTraceviewLauncher(IConfigurationElement[] configElements) + throws CoreException { + ArrayList list = new ArrayList(); + + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the class + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof ITraceviewLauncher) { + list.add((ITraceviewLauncher) obj); + } + } + + return list.toArray(new ITraceviewLauncher[list.size()]); + } + + /** + * Returns the classes that implement {@link IClientAction} in each of the + * extensions that extend clientAction extension point. + * + * @throws CoreException + */ + private List instantiateClientSpecificActions(IConfigurationElement[] elements) throws CoreException { + if (elements == null || elements.length == 0) { + return Collections.emptyList(); + } + + List extensions = new ArrayList(1); + + for (IConfigurationElement e : elements) { + Object o = e.createExecutableExtension("class"); //$NON-NLS-1$ + if (o instanceof IClientAction) { + extensions.add((IClientAction) o); + } + } + + return extensions; + } + + public static Display getDisplay() { + IWorkbench bench = sPlugin.getWorkbench(); + if (bench != null) { + return bench.getDisplay(); + } + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + @Override + public void stop(BundleContext context) throws Exception { + AndroidDebugBridge.removeDeviceChangeListener(this); + + AndroidDebugBridge.terminate(); + + mRed.dispose(); + mImageFactory.dispose(); + sPlugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static DdmsPlugin getDefault() { + return sPlugin; + } + + public static String getAdb() { + return sAdbLocation; + } + + public static File getPlatformToolsFolder() { + return new File(sAdbLocation).getParentFile(); + } + + public static String getToolsFolder() { + return sToolsFolder; + } + + public static String getHprofConverter() { + return sHprofConverter; + } + + /** + * Stores the adb location. This returns true if the location is an existing + * file. + */ + private static boolean setToolsLocation(String adbLocation, String hprofConvLocation, String traceViewLocation) { + + File adb = new File(adbLocation); + File hprofConverter = new File(hprofConvLocation); + File traceview = new File(traceViewLocation); + + String missing = ""; + if (adb.isFile() == false) { + missing += adb.getAbsolutePath() + " "; + } + if (hprofConverter.isFile() == false) { + missing += hprofConverter.getAbsolutePath() + " "; + } + if (traceview.isFile() == false) { + missing += traceview.getAbsolutePath() + " "; + } + + if (missing.length() > 0) { + String msg = String.format("DDMS files not found: %1$s", missing); + Log.e("DDMS", msg); + Status status = new Status(IStatus.ERROR, PLUGIN_ID, msg, null /* exception */); + getDefault().getLog().log(status); + return false; + } + + sAdbLocation = adbLocation; + sHprofConverter = hprofConverter.getAbsolutePath(); + DdmUiPreferences.setTraceviewLocation(traceview.getAbsolutePath()); + + sToolsFolder = traceview.getParent(); + + return true; + } + + /** + * Set the location of the adb executable and optionally starts adb + * + * @param adb + * location of adb + * @param startAdb + * flag to start adb + */ + public static void setToolsLocation(String adbLocation, boolean startAdb, String hprofConvLocation, + String traceViewLocation) { + + if (setToolsLocation(adbLocation, hprofConvLocation, traceViewLocation)) { + // starts the server in a thread in case this is blocking. + if (startAdb) { + new Thread() { + @Override + public void run() { + // create and start the bridge + try { + AndroidDebugBridge.createBridge(sAdbLocation, false /* forceNewBridge */); + } catch (Throwable t) { + Status status = new Status(IStatus.ERROR, PLUGIN_ID, "Failed to create AndroidDebugBridge", + t); + getDefault().getLog().log(status); + } + } + }.start(); + } + } + } + + /** + * Returns whether there are implementations of the debuggerConnectors + * extension point. + *

+ * This is guaranteed to return the correct value as soon as the plug-in is + * loaded. + */ + public boolean hasDebuggerConnectors() { + return mHasDebuggerConnectors; + } + + /** + * Returns the implementations of {@link IDebuggerConnector}. + *

+ * There may be a small amount of time right after the plug-in load where + * this can return null even if there are implementation. + *

+ * Since the use of the implementation likely require user input, the UI can + * use {@link #hasDebuggerConnectors()} to know if there are implementations + * before they are loaded. + */ + public IDebuggerConnector[] getDebuggerConnectors() { + return mDebuggerConnectors; + } + + public synchronized void addSelectionListener(ISelectionListener listener) { + mListeners.add(listener); + + // notify the new listener of the current selection + listener.selectionChanged(mCurrentDevice); + listener.selectionChanged(mCurrentClient); + } + + public synchronized void removeSelectionListener(ISelectionListener listener) { + mListeners.remove(listener); + } + + public synchronized void setListeningState(boolean state) { + mListeningToUiSelection = state; + } + + /** + * Sent when the a device is connected to the {@link AndroidDebugBridge}. + *

+ * This is sent from a non UI thread. + * + * @param device + * the new device. + * + * @see IDeviceChangeListener#deviceConnected(IDevice) + */ + @Override + public void deviceConnected(IDevice device) { + // if we are listening to selection coming from the ui, then we do + // nothing, as + // any change in the devices/clients, will be handled by the UI, and + // we'll receive + // selection notification through our implementation of + // IUiSelectionListener. + if (mListeningToUiSelection == false) { + if (mCurrentDevice == null) { + handleDefaultSelection(device); + } + } + } + + /** + * Sent when the a device is disconnected to the {@link AndroidDebugBridge}. + *

+ * This is sent from a non UI thread. + * + * @param device + * the new device. + * + * @see IDeviceChangeListener#deviceDisconnected(IDevice) + */ + @Override + public void deviceDisconnected(IDevice device) { + // if we are listening to selection coming from the ui, then we do + // nothing, as + // any change in the devices/clients, will be handled by the UI, and + // we'll receive + // selection notification through our implementation of + // IUiSelectionListener. + if (mListeningToUiSelection == false) { + // test if the disconnected device was the default selection. + if (mCurrentDevice == device) { + // try to find a new device + AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); + if (bridge != null) { + // get the device list + IDevice[] devices = bridge.getDevices(); + + // check if we still have devices + if (devices.length == 0) { + handleDefaultSelection((IDevice) null); + } else { + handleDefaultSelection(devices[0]); + } + } else { + handleDefaultSelection((IDevice) null); + } + } + } + } + + /** + * Sent when a device data changed, or when clients are started/terminated + * on the device. + *

+ * This is sent from a non UI thread. + * + * @param device + * the device that was updated. + * @param changeMask + * the mask indicating what changed. + * + * @see IDeviceChangeListener#deviceChanged(IDevice) + */ + @Override + public void deviceChanged(IDevice device, int changeMask) { + // if we are listening to selection coming from the ui, then we do + // nothing, as + // any change in the devices/clients, will be handled by the UI, and + // we'll receive + // selection notification through our implementation of + // IUiSelectionListener. + if (mListeningToUiSelection == false) { + + // check if this is our device + if (device == mCurrentDevice) { + if (mCurrentClient == null) { + handleDefaultSelection(device); + } else { + // get the clients and make sure ours is still in there. + Client[] clients = device.getClients(); + boolean foundClient = false; + for (Client client : clients) { + if (client == mCurrentClient) { + foundClient = true; + break; + } + } + + // if we haven't found our client, lets look for a new one + if (foundClient == false) { + mCurrentClient = null; + handleDefaultSelection(device); + } + } + } + } + } + + /** + * Sent when a new {@link IDevice} and {@link Client} are selected. + * + * @param selectedDevice + * the selected device. If null, no devices are selected. + * @param selectedClient + * The selected client. If null, no clients are selected. + */ + @Override + public synchronized void selectionChanged(IDevice selectedDevice, Client selectedClient) { + if (mCurrentDevice != selectedDevice) { + mCurrentDevice = selectedDevice; + + // notify of the new default device + for (ISelectionListener listener : mListeners) { + listener.selectionChanged(mCurrentDevice); + } + } + + if (mCurrentClient != selectedClient) { + mCurrentClient = selectedClient; + + // notify of the new default client + for (ISelectionListener listener : mListeners) { + listener.selectionChanged(mCurrentClient); + } + } + } + + /** + * Handles a default selection of a {@link IDevice} and {@link Client}. + * + * @param device + * the selected device + */ + private void handleDefaultSelection(final IDevice device) { + // because the listener expect to receive this from the UI thread, and + // this is called + // from the AndroidDebugBridge notifications, we need to run this in the + // UI thread. + try { + Display display = getDisplay(); + + display.asyncExec(new Runnable() { + @Override + public void run() { + // set the new device if different. + boolean newDevice = false; + if (mCurrentDevice != device) { + mCurrentDevice = device; + newDevice = true; + + // notify of the new default device + for (ISelectionListener listener : mListeners) { + listener.selectionChanged(mCurrentDevice); + } + } + + if (device != null) { + // if this is a device switch or the same device but we + // didn't find a valid + // client the last time, we go look for a client to use + // again. + if (newDevice || mCurrentClient == null) { + // now get the new client + Client[] clients = device.getClients(); + if (clients.length > 0) { + handleDefaultSelection(clients[0]); + } else { + handleDefaultSelection((Client) null); + } + } + } else { + handleDefaultSelection((Client) null); + } + } + }); + } catch (SWTException e) { + // display is disposed. Do nothing since we're quitting anyway. + } + } + + private void handleDefaultSelection(Client client) { + mCurrentClient = client; + + // notify of the new default client + for (ISelectionListener listener : mListeners) { + listener.selectionChanged(mCurrentClient); + } + } + + /** + * Prints a message, associated with a project to the specified stream + * + * @param stream + * The stream to write to + * @param tag + * The tag associated to the message. Can be null + * @param message + * The message to print. + */ + private static synchronized void printToStream(MessageConsoleStream stream, String tag, String message) { + String dateTag = getMessageTag(tag); + + stream.print(dateTag); + if (!dateTag.endsWith(" ")) { + stream.print(" "); //$NON-NLS-1$ + } + stream.println(message); + } + + /** + * Creates a string containing the current date/time, and the tag + * + * @param tag + * The tag associated to the message. Can be null + * @return The dateTag + */ + private static String getMessageTag(String tag) { + Calendar c = Calendar.getInstance(); + + if (tag == null) { + return String.format(Messages.DdmsPlugin_Message_Tag_Mask_1, c); + } + + return String.format(Messages.DdmsPlugin_Message_Tag_Mask_2, c, tag); + } + + /** + * Implementation of com.android.ddmuilib.StackTracePanel.ISourceRevealer. + */ + @Override + public void reveal(String applicationName, String className, int line) { + JavaSourceRevealer.reveal(applicationName, className, line); + } + + public boolean launchTraceview(String osPath) { + if (mTraceviewLaunchers != null) { + for (ITraceviewLauncher launcher : mTraceviewLaunchers) { + try { + if (launcher.openFile(osPath)) { + return true; + } + } catch (Throwable t) { + // ignore, we'll just not use this implementation. + } + } + } + + return false; + } + + /** + * Returns the list of clients that extend the clientAction extension point. + */ + @NonNull + public synchronized List getClientSpecificActions() { + if (mClientSpecificActions == null) { + // get available client specific action extensions + IConfigurationElement[] elements = findConfigElements("org.eclipse.andmore.ddms.clientAction"); //$NON-NLS-1$ + try { + mClientSpecificActions = instantiateClientSpecificActions(elements); + } catch (CoreException e) { + mClientSpecificActions = Collections.emptyList(); + } + } + + return mClientSpecificActions; + } + + private LogCatMonitor mLogCatMonitor; + + public void startLogCatMonitor(IDevice device) { + if (mLogCatMonitor == null) { + mLogCatMonitor = new LogCatMonitor(getDebuggerConnectors(), getPreferenceStore()); + } + + mLogCatMonitor.monitorDevice(device); + } + + /** + * Returns an image descriptor for the image file at the given plug-in + * relative path + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/AllocTrackerView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/AllocTrackerView.java index 3c5b1950..f865dd51 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/AllocTrackerView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/AllocTrackerView.java @@ -1,47 +1,51 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmuilib.AllocationPanel; - -import org.eclipse.swt.widgets.Composite; - -public class AllocTrackerView extends TableView { - - public static final String ID = "org.eclipse.andmore.ddms.views.AllocTrackerView"; //$NON-NLS-1$ - private AllocationPanel mPanel; - - public AllocTrackerView() { - } - - @Override - public void createPartControl(Composite parent) { - mPanel = new AllocationPanel(); - mPanel.createPanel(parent); - - setSelectionDependentPanel(mPanel); - - // listen to focus changes for table(s) of the panel. - setupTableFocusListener(mPanel, parent); - } - - @Override - public void setFocus() { - mPanel.setFocus(); - } - -} +/* + * 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmuilib.AllocationPanel; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.swt.widgets.Composite; + +public class AllocTrackerView extends TableView { + + public static final String ID = "org.eclipse.andmore.ddms.views.AllocTrackerView"; //$NON-NLS-1$ + private AllocationPanel mPanel; + private ImageFactory mImageFactory; + + public AllocTrackerView() { + super(); + mImageFactory = DdmsPlugin.getDefault().getImageFactory(); + } + + @Override + public void createPartControl(Composite parent) { + mPanel = new AllocationPanel(mImageFactory); + mPanel.createPanel(parent); + + setSelectionDependentPanel(mPanel); + + // listen to focus changes for table(s) of the panel. + setupTableFocusListener(mPanel, parent); + } + + @Override + public void setFocus() { + mPanel.setFocus(); + } +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/DeviceView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/DeviceView.java index a467a1a0..2aa62d79 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/DeviceView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/DeviceView.java @@ -1,839 +1,839 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import com.android.ddmlib.ClientData.IHprofDumpHandler; -import com.android.ddmlib.ClientData.MethodProfilingStatus; -import com.android.ddmlib.CollectingOutputReceiver; -import com.android.ddmlib.DdmPreferences; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.SyncException; -import com.android.ddmlib.SyncService; -import com.android.ddmlib.SyncService.ISyncProgressMonitor; -import com.android.ddmlib.TimeoutException; -import com.android.ddmuilib.DevicePanel; -import com.android.ddmuilib.DevicePanel.IUiSelectionListener; -import com.android.ddmuilib.ImageLoader; -import com.android.ddmuilib.ScreenShotDialog; -import com.android.ddmuilib.SyncProgressHelper; -import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; -import com.android.ddmuilib.handler.BaseFileHandler; -import com.android.ddmuilib.handler.MethodProfilingHandler; -import com.android.uiautomator.UiAutomatorHelper; -import com.android.uiautomator.UiAutomatorHelper.UiAutomatorException; -import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult; -import com.google.common.io.Files; - -import org.eclipse.andmore.ddms.DdmsPlugin; -import org.eclipse.andmore.ddms.IClientAction; -import org.eclipse.andmore.ddms.IDebuggerConnector; -import org.eclipse.andmore.ddms.editors.UiAutomatorViewer; -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; -import org.eclipse.andmore.ddms.systrace.ISystraceOptions; -import org.eclipse.andmore.ddms.systrace.ISystraceOptionsDialog; -import org.eclipse.andmore.ddms.systrace.SystraceOptionsDialogV1; -import org.eclipse.andmore.ddms.systrace.SystraceOptionsDialogV2; -import org.eclipse.andmore.ddms.systrace.SystraceOutputParser; -import org.eclipse.andmore.ddms.systrace.SystraceTask; -import org.eclipse.andmore.ddms.systrace.SystraceVersionDetector; -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.filesystem.IFileStore; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.dialogs.ProgressMonitorDialog; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.ide.IDE; -import org.eclipse.ui.part.ViewPart; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class DeviceView extends ViewPart implements IUiSelectionListener, IClientChangeListener { - - private final static boolean USE_SELECTED_DEBUG_PORT = true; - - public static final String ID = "org.eclipse.andmore.ddms.views.DeviceView"; //$NON-NLS-1$ - - private static DeviceView sThis; - - private Shell mParentShell; - private DevicePanel mDeviceList; - - private Action mResetAdbAction; - private Action mCaptureAction; - private Action mViewUiAutomatorHierarchyAction; - private Action mSystraceAction; - private Action mUpdateThreadAction; - private Action mUpdateHeapAction; - private Action mGcAction; - private Action mKillAppAction; - private Action mDebugAction; - private Action mHprofAction; - private Action mTracingAction; - - private ImageDescriptor mTracingStartImage; - private ImageDescriptor mTracingStopImage; - - public class HProfHandler extends BaseFileHandler implements IHprofDumpHandler { - public final static String ACTION_SAVE = "hprof.save"; //$NON-NLS-1$ - public final static String ACTION_OPEN = "hprof.open"; //$NON-NLS-1$ - - public final static String DOT_HPROF = ".hprof"; //$NON-NLS-1$ - - HProfHandler(Shell parentShell) { - super(parentShell); - } - - @Override - protected String getDialogTitle() { - return Messages.DeviceView_HPROF_Error; - } - - @Override - public void onEndFailure(final Client client, final String message) { - mParentShell.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - try { - displayErrorFromUiThread(Messages.DeviceView_Unable_Create_HPROF_For_Application, client - .getClientData().getClientDescription(), message != null ? message + "\n\n" : ""); //$NON-NLS-1$ //$NON-NLS-2$ - } finally { - // this will make sure the dump hprof button is - // re-enabled for the - // current selection. as the client is finished dumping - // an hprof file - doSelectionChanged(mDeviceList.getSelectedClient()); - } - } - }); - } - - @Override - public void onSuccess(final String remoteFilePath, final Client client) { - mParentShell.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - final IDevice device = client.getDevice(); - try { - // get the sync service to pull the HPROF file - final SyncService sync = client.getDevice().getSyncService(); - if (sync != null) { - // get from the preference what action to take - IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); - String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); - - if (ACTION_OPEN.equals(value)) { - File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ - final String tempPath = temp.getAbsolutePath(); - SyncProgressHelper.run(new SyncRunnable() { - - @Override - public void run(ISyncProgressMonitor monitor) throws SyncException, IOException, - TimeoutException { - sync.pullFile(remoteFilePath, tempPath, monitor); - } - - @Override - public void close() { - sync.close(); - } - }, String.format(Messages.DeviceView_Pulling_From_Device, remoteFilePath), mParentShell); - - open(tempPath); - } else { - // default action is ACTION_SAVE - promptAndPull(sync, client.getClientData().getClientDescription() + DOT_HPROF, - remoteFilePath, Messages.DeviceView_Save_HPROF_File); - - } - } else { - displayErrorFromUiThread( - Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_First_Message, - device.getSerialNumber()); - } - } catch (SyncException e) { - if (e.wasCanceled() == false) { - displayErrorFromUiThread(Messages.DeviceView_Unable_Download_HPROF_From_Device_Two_Param, - device.getSerialNumber(), e.getMessage()); - } - } catch (Exception e) { - displayErrorFromUiThread( - Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_Second_Message, - device.getSerialNumber()); - - } finally { - // this will make sure the dump hprof button is - // re-enabled for the - // current selection. as the client is finished dumping - // an hprof file - doSelectionChanged(mDeviceList.getSelectedClient()); - } - } - }); - } - - @Override - public void onSuccess(final byte[] data, final Client client) { - mParentShell.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - // get from the preference what action to take - IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); - String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); - - if (ACTION_OPEN.equals(value)) { - try { - // no need to give an extension since we're going to - // convert the - // file anyway after. - File tempFile = saveTempFile(data, null /* extension */); - open(tempFile.getAbsolutePath()); - } catch (Exception e) { - String errorMsg = e.getMessage(); - displayErrorFromUiThread(Messages.DeviceView_Failed_To_Save_HPROF_Data, - errorMsg != null ? ":\n" + errorMsg : "."); //$NON-NLS-1$ //$NON-NLS-2$ - } - } else { - // default action is ACTION_SAVE - promptAndSave(client.getClientData().getClientDescription() + DOT_HPROF, data, - Messages.DeviceView_Save_HPROF_File); - } - } - }); - } - - private void open(String path) throws IOException, InterruptedException, PartInitException { - // make a temp file to convert the hprof into something - // readable by normal tools - File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ - String tempPath = temp.getAbsolutePath(); - - String[] command = new String[3]; - command[0] = DdmsPlugin.getHprofConverter(); - command[1] = path; - command[2] = tempPath; - - Process p = Runtime.getRuntime().exec(command); - p.waitFor(); - - IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(tempPath)); - if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { - // before we open the file in an editor window, we make sure the - // current - // workbench page has an editor area (typically the ddms - // perspective doesn't). - IWorkbench workbench = PlatformUI.getWorkbench(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - IWorkbenchPage page = window.getActivePage(); - if (page == null) { - return; - } - - if (page.isEditorAreaVisible() == false) { - IAdaptable input; - input = page.getInput(); - try { - workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", //$NON-NLS-1$ - window, input); - } catch (WorkbenchException e) { - } - } - - IDE.openEditorOnFileStore(page, fileStore); - } - } - } - - public DeviceView() { - // the view is declared with allowMultiple="false" so we - // can safely do this. - sThis = this; - } - - public static DeviceView getInstance() { - return sThis; - } - - @Override - public void createPartControl(Composite parent) { - mParentShell = parent.getShell(); - - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - - mDeviceList = new DevicePanel(USE_SELECTED_DEBUG_PORT); - mDeviceList.createPanel(parent); - mDeviceList.addSelectionListener(this); - - DdmsPlugin plugin = DdmsPlugin.getDefault(); - mDeviceList.addSelectionListener(plugin); - plugin.setListeningState(true); - - mCaptureAction = new Action(Messages.DeviceView_Screen_Capture) { - @Override - public void run() { - ScreenShotDialog dlg = new ScreenShotDialog(DdmsPlugin.getDisplay().getActiveShell()); - dlg.open(mDeviceList.getSelectedDevice()); - } - }; - mCaptureAction.setToolTipText(Messages.DeviceView_Screen_Capture_Tooltip); - mCaptureAction.setImageDescriptor(loader.loadDescriptor("capture.png")); //$NON-NLS-1$ - - mViewUiAutomatorHierarchyAction = new Action("Dump View Hierarchy for UI Automator") { - @Override - public void run() { - takeUiAutomatorSnapshot(mDeviceList.getSelectedDevice(), DdmsPlugin.getDisplay().getActiveShell()); - } - }; - mViewUiAutomatorHierarchyAction.setToolTipText("Dump View Hierarchy for UI Automator"); - mViewUiAutomatorHierarchyAction.setImageDescriptor(DdmsPlugin.getImageDescriptor("icons/uiautomator.png")); //$NON-NLS-1$ - - mSystraceAction = new Action("Capture System Wide Trace") { - @Override - public void run() { - launchSystrace(mDeviceList.getSelectedDevice(), DdmsPlugin.getDisplay().getActiveShell()); - } - }; - mSystraceAction.setToolTipText("Capture system wide trace using Android systrace"); - mSystraceAction.setImageDescriptor(DdmsPlugin.getImageDescriptor("icons/systrace.png")); //$NON-NLS-1$ - mSystraceAction.setEnabled(true); - - mResetAdbAction = new Action(Messages.DeviceView_Reset_ADB) { - @Override - public void run() { - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - if (bridge != null) { - if (bridge.restart() == false) { - // get the current Display - final Display display = DdmsPlugin.getDisplay(); - - // dialog box only run in ui thread.. - display.asyncExec(new Runnable() { - @Override - public void run() { - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, Messages.DeviceView_ADB_Error, - Messages.DeviceView_ADB_Failed_Restart); - } - }); - } - } - } - }; - mResetAdbAction.setToolTipText(Messages.DeviceView_Reset_ADB_Host_Deamon); - mResetAdbAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() - .getImageDescriptor(ISharedImages.IMG_OBJS_WARN_TSK)); - - mKillAppAction = new Action() { - @Override - public void run() { - mDeviceList.killSelectedClient(); - } - }; - - mKillAppAction.setText(Messages.DeviceView_Stop_Process); - mKillAppAction.setToolTipText(Messages.DeviceView_Stop_Process_Tooltip); - mKillAppAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HALT)); - - mGcAction = new Action() { - @Override - public void run() { - mDeviceList.forceGcOnSelectedClient(); - } - }; - - mGcAction.setText(Messages.DeviceView_Cause_GC); - mGcAction.setToolTipText(Messages.DeviceView_Cause_GC_Tooltip); - mGcAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_GC)); - - mHprofAction = new Action() { - @Override - public void run() { - mDeviceList.dumpHprof(); - doSelectionChanged(mDeviceList.getSelectedClient()); - } - }; - mHprofAction.setText(Messages.DeviceView_Dump_HPROF_File); - mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Tooltip); - mHprofAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HPROF)); - - mUpdateHeapAction = new Action(Messages.DeviceView_Update_Heap, IAction.AS_CHECK_BOX) { - @Override - public void run() { - boolean enable = mUpdateHeapAction.isChecked(); - mDeviceList.setEnabledHeapOnSelectedClient(enable); - } - }; - mUpdateHeapAction.setToolTipText(Messages.DeviceView_Update_Heap_Tooltip); - mUpdateHeapAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HEAP)); - - mUpdateThreadAction = new Action(Messages.DeviceView_Threads, IAction.AS_CHECK_BOX) { - @Override - public void run() { - boolean enable = mUpdateThreadAction.isChecked(); - mDeviceList.setEnabledThreadOnSelectedClient(enable); - } - }; - mUpdateThreadAction.setToolTipText(Messages.DeviceView_Threads_Tooltip); - mUpdateThreadAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_THREAD)); - - mTracingAction = new Action() { - @Override - public void run() { - mDeviceList.toggleMethodProfiling(); - } - }; - mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); - mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); - mTracingStartImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_START); - mTracingStopImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_STOP); - mTracingAction.setImageDescriptor(mTracingStartImage); - - mDebugAction = new Action(Messages.DeviceView_Debug_Process) { - @Override - public void run() { - if (DdmsPlugin.getDefault().hasDebuggerConnectors()) { - Client currentClient = mDeviceList.getSelectedClient(); - if (currentClient != null) { - ClientData clientData = currentClient.getClientData(); - - // make sure the client can be debugged - switch (clientData.getDebuggerConnectionStatus()) { - case ERROR: { - Display display = DdmsPlugin.getDisplay(); - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, - Messages.DeviceView_Process_Debug_Already_In_Use); - return; - } - case ATTACHED: { - Display display = DdmsPlugin.getDisplay(); - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, - Messages.DeviceView_Process_Already_Being_Debugged); - return; - } - } - - // get the name of the client - String packageName = clientData.getClientDescription(); - if (packageName != null) { - - // try all connectors till one returns true. - IDebuggerConnector[] connectors = DdmsPlugin.getDefault().getDebuggerConnectors(); - - if (connectors != null) { - for (IDebuggerConnector connector : connectors) { - try { - if (connector.connectDebugger(packageName, - currentClient.getDebuggerListenPort(), - DdmPreferences.getSelectedDebugPort())) { - return; - } - } catch (Throwable t) { - // ignore, we'll just not use this - // implementation - } - } - } - - // if we get to this point, then we failed to find a - // project - // that matched the application to debug - Display display = DdmsPlugin.getDisplay(); - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, - String.format(Messages.DeviceView_Debug_Session_Failed, packageName)); - } - } - } - } - }; - mDebugAction.setToolTipText(Messages.DeviceView_Debug_Process_Tooltip); - mDebugAction.setImageDescriptor(loader.loadDescriptor("debug-attach.png")); //$NON-NLS-1$ - mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors()); - - placeActions(); - - // disabling all action buttons - selectionChanged(null, null); - - ClientData.setHprofDumpHandler(new HProfHandler(mParentShell)); - AndroidDebugBridge.addClientChangeListener(this); - ClientData.setMethodProfilingHandler(new MethodProfilingHandler(mParentShell) { - @Override - protected void open(String tempPath) { - if (DdmsPlugin.getDefault().launchTraceview(tempPath) == false) { - super.open(tempPath); - } - } - }); - } - - private void takeUiAutomatorSnapshot(final IDevice device, final Shell shell) { - ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); - try { - dialog.run(true, false, new IRunnableWithProgress() { - @Override - public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - UiAutomatorResult result = null; - try { - result = UiAutomatorHelper.takeSnapshot(device, monitor); - } catch (UiAutomatorException e) { - throw new InvocationTargetException(e); - } finally { - monitor.done(); - } - - UiAutomatorViewer.openEditor(result); - } - }); - } catch (Exception e) { - Throwable t = e; - if (e instanceof InvocationTargetException) { - t = ((InvocationTargetException) e).getTargetException(); - } - Status s = new Status(IStatus.ERROR, DdmsPlugin.PLUGIN_ID, "Error obtaining UI hierarchy", t); - ErrorDialog.openError(shell, "UI Automator", "Unexpected error while obtaining UI hierarchy", s); - } - }; - - private void launchSystrace(final IDevice device, final Shell parentShell) { - final File systraceAssets = new File(DdmsPlugin.getPlatformToolsFolder(), "systrace"); //$NON-NLS-1$ - if (!systraceAssets.isDirectory()) { - MessageDialog.openError(parentShell, "Systrace", - "Updated version of platform-tools (18.0.1 or greater) is required.\n" - + "Please update your platform-tools using SDK Manager."); - return; - } - - SystraceVersionDetector detector = new SystraceVersionDetector(device); - try { - new ProgressMonitorDialog(parentShell).run(true, false, detector); - } catch (InvocationTargetException e) { - MessageDialog.openError(parentShell, "Systrace", "Unexpected error while detecting atrace version: " + e); - return; - } catch (InterruptedException e) { - return; - } - - final ISystraceOptionsDialog dlg; - if (detector.getVersion() == SystraceVersionDetector.SYSTRACE_V1) { - dlg = new SystraceOptionsDialogV1(parentShell); - } else { - Client[] clients = device.getClients(); - List apps = new ArrayList(clients.length); - for (int i = 0; i < clients.length; i++) { - String name = clients[i].getClientData().getClientDescription(); - if (name != null && !name.isEmpty()) { - apps.add(name); - } - } - dlg = new SystraceOptionsDialogV2(parentShell, detector.getTags(), apps); - } - - if (dlg.open() != Window.OK) { - return; - } - - final ISystraceOptions options = dlg.getSystraceOptions(); - - // set trace tag if necessary: - // adb shell setprop debug.atrace.tags.enableflags - String tag = options.getTags(); - if (tag != null) { - CountDownLatch setTagLatch = new CountDownLatch(1); - CollectingOutputReceiver receiver = new CollectingOutputReceiver(setTagLatch); - try { - String cmd = "setprop debug.atrace.tags.enableflags " + tag; - device.executeShellCommand(cmd, receiver); - setTagLatch.await(5, TimeUnit.SECONDS); - } catch (Exception e) { - MessageDialog.openError(parentShell, "Systrace", "Unexpected error while setting trace tags: " + e); - return; - } - - String shellOutput = receiver.getOutput(); - if (shellOutput.contains("Error type")) { //$NON-NLS-1$ - throw new RuntimeException(receiver.getOutput()); - } - } - - // obtain the output of "adb shell atrace " and generate - // the html file - ProgressMonitorDialog d = new ProgressMonitorDialog(parentShell); - try { - d.run(true, true, new IRunnableWithProgress() { - @Override - public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - boolean COMPRESS_DATA = true; - - monitor.setTaskName("Collecting Trace Information"); - final String atraceOptions = options.getOptions() + (COMPRESS_DATA ? " -z" : ""); - SystraceTask task = new SystraceTask(device, atraceOptions); - Thread t = new Thread(task, "Systrace Output Receiver"); - t.start(); - - // check if the user has cancelled tracing every so often - while (true) { - t.join(1000); - - if (t.isAlive()) { - if (monitor.isCanceled()) { - task.cancel(); - return; - } - } else { - break; - } - } - - if (task.getError() != null) { - throw new RuntimeException(task.getError()); - } - - monitor.setTaskName("Saving trace information"); - SystraceOutputParser parser = new SystraceOutputParser(COMPRESS_DATA, SystraceOutputParser - .getJs(systraceAssets), SystraceOutputParser.getCss(systraceAssets), SystraceOutputParser - .getHtmlPrefix(systraceAssets), SystraceOutputParser.getHtmlSuffix(systraceAssets)); - - parser.parse(task.getAtraceOutput()); - - String html = parser.getSystraceHtml(); - try { - Files.write(html.getBytes(), new File(dlg.getTraceFilePath())); - } catch (IOException e) { - throw new InvocationTargetException(e); - } - } - }); - } catch (InvocationTargetException e) { - ErrorDialog.openError(parentShell, "Systrace", "Unable to collect system trace.", new Status(IStatus.ERROR, - DdmsPlugin.PLUGIN_ID, "Unexpected error while collecting system trace.", e.getCause())); - } catch (InterruptedException ignore) { - } - } - - @Override - public void setFocus() { - mDeviceList.setFocus(); - } - - /** - * Sent when a new {@link IDevice} and {@link Client} are selected. - * - * @param selectedDevice - * the selected device. If null, no devices are selected. - * @param selectedClient - * The selected client. If null, no clients are selected. - */ - @Override - public void selectionChanged(IDevice selectedDevice, Client selectedClient) { - // update the buttons - doSelectionChanged(selectedClient); - doSelectionChanged(selectedDevice); - } - - private void doSelectionChanged(Client selectedClient) { - // update the buttons - if (selectedClient != null) { - if (USE_SELECTED_DEBUG_PORT) { - // set the client as the debug client - selectedClient.setAsSelectedClient(); - } - - mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors()); - mKillAppAction.setEnabled(true); - mGcAction.setEnabled(true); - - mUpdateHeapAction.setEnabled(true); - mUpdateHeapAction.setChecked(selectedClient.isHeapUpdateEnabled()); - - mUpdateThreadAction.setEnabled(true); - mUpdateThreadAction.setChecked(selectedClient.isThreadUpdateEnabled()); - - ClientData data = selectedClient.getClientData(); - - if (data.hasFeature(ClientData.FEATURE_HPROF)) { - mHprofAction.setEnabled(data.hasPendingHprofDump() == false); - mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); - } else { - mHprofAction.setEnabled(false); - mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Not_Supported_By_VM); - } - - if (data.hasFeature(ClientData.FEATURE_PROFILING)) { - mTracingAction.setEnabled(true); - if (data.getMethodProfilingStatus() == MethodProfilingStatus.TRACER_ON - || data.getMethodProfilingStatus() == MethodProfilingStatus.SAMPLER_ON) { - mTracingAction.setToolTipText(Messages.DeviceView_Stop_Method_Profiling_Tooltip); - mTracingAction.setText(Messages.DeviceView_Stop_Method_Profiling); - mTracingAction.setImageDescriptor(mTracingStopImage); - } else { - mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); - mTracingAction.setImageDescriptor(mTracingStartImage); - mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); - } - } else { - mTracingAction.setEnabled(false); - mTracingAction.setImageDescriptor(mTracingStartImage); - mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Not_Suported_By_Vm); - mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); - } - } else { - if (USE_SELECTED_DEBUG_PORT) { - // set the client as the debug client - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - if (bridge != null) { - bridge.setSelectedClient(null); - } - } - - mDebugAction.setEnabled(false); - mKillAppAction.setEnabled(false); - mGcAction.setEnabled(false); - mUpdateHeapAction.setChecked(false); - mUpdateHeapAction.setEnabled(false); - mUpdateThreadAction.setEnabled(false); - mUpdateThreadAction.setChecked(false); - mHprofAction.setEnabled(false); - - mHprofAction.setEnabled(false); - mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); - - mTracingAction.setEnabled(false); - mTracingAction.setImageDescriptor(mTracingStartImage); - mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); - mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); - } - - for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { - a.selectedClientChanged(selectedClient); - } - } - - private void doSelectionChanged(IDevice selectedDevice) { - boolean validDevice = selectedDevice != null; - - mCaptureAction.setEnabled(validDevice); - mViewUiAutomatorHierarchyAction.setEnabled(validDevice); - mSystraceAction.setEnabled(validDevice); - } - - /** - * Place the actions in the ui. - */ - private final void placeActions() { - IActionBars actionBars = getViewSite().getActionBars(); - - // first in the menu - IMenuManager menuManager = actionBars.getMenuManager(); - menuManager.removeAll(); - menuManager.add(mDebugAction); - menuManager.add(new Separator()); - menuManager.add(mUpdateHeapAction); - menuManager.add(mHprofAction); - menuManager.add(mGcAction); - menuManager.add(new Separator()); - menuManager.add(mUpdateThreadAction); - menuManager.add(mTracingAction); - menuManager.add(new Separator()); - menuManager.add(mKillAppAction); - menuManager.add(new Separator()); - menuManager.add(mCaptureAction); - menuManager.add(new Separator()); - menuManager.add(mViewUiAutomatorHierarchyAction); - menuManager.add(new Separator()); - menuManager.add(mSystraceAction); - menuManager.add(new Separator()); - menuManager.add(mResetAdbAction); - for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { - menuManager.add(a.getAction()); - } - - // and then in the toolbar - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - toolBarManager.removeAll(); - toolBarManager.add(mDebugAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mUpdateHeapAction); - toolBarManager.add(mHprofAction); - toolBarManager.add(mGcAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mUpdateThreadAction); - toolBarManager.add(mTracingAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mKillAppAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mCaptureAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mViewUiAutomatorHierarchyAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mSystraceAction); - for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { - toolBarManager.add(a.getAction()); - } - } - - @Override - public void clientChanged(final Client client, int changeMask) { - if ((changeMask & Client.CHANGE_METHOD_PROFILING_STATUS) == Client.CHANGE_METHOD_PROFILING_STATUS) { - if (mDeviceList.getSelectedClient() == client) { - mParentShell.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - // force refresh of the button enabled state. - doSelectionChanged(client); - } - }); - } - } - } -} +/* + * 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; +import com.android.ddmlib.Client; +import com.android.ddmlib.ClientData; +import com.android.ddmlib.ClientData.IHprofDumpHandler; +import com.android.ddmlib.ClientData.MethodProfilingStatus; +import com.android.ddmlib.CollectingOutputReceiver; +import com.android.ddmlib.DdmPreferences; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.SyncException; +import com.android.ddmlib.SyncService; +import com.android.ddmlib.SyncService.ISyncProgressMonitor; +import com.android.ddmlib.TimeoutException; +import com.android.ddmuilib.DevicePanel; +import com.android.ddmuilib.DevicePanel.IUiSelectionListener; +import com.android.ddmuilib.ScreenShotDialog; +import com.android.ddmuilib.SyncProgressHelper; +import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; +import com.android.ddmuilib.handler.BaseFileHandler; +import com.android.ddmuilib.handler.MethodProfilingHandler; +import com.android.uiautomator.UiAutomatorHelper; +import com.android.uiautomator.UiAutomatorHelper.UiAutomatorException; +import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult; +import com.google.common.io.Files; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.andmore.ddms.IClientAction; +import org.eclipse.andmore.ddms.IDebuggerConnector; +import org.eclipse.andmore.ddms.editors.UiAutomatorViewer; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; +import org.eclipse.andmore.ddms.systrace.ISystraceOptions; +import org.eclipse.andmore.ddms.systrace.ISystraceOptionsDialog; +import org.eclipse.andmore.ddms.systrace.SystraceOptionsDialogV1; +import org.eclipse.andmore.ddms.systrace.SystraceOptionsDialogV2; +import org.eclipse.andmore.ddms.systrace.SystraceOutputParser; +import org.eclipse.andmore.ddms.systrace.SystraceTask; +import org.eclipse.andmore.ddms.systrace.SystraceVersionDetector; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.ViewPart; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class DeviceView extends ViewPart implements IUiSelectionListener, IClientChangeListener { + + private final static boolean USE_SELECTED_DEBUG_PORT = true; + + public static final String ID = "org.eclipse.andmore.ddms.views.DeviceView"; //$NON-NLS-1$ + + private static DeviceView sThis; + + private Shell mParentShell; + private DevicePanel mDeviceList; + + private Action mResetAdbAction; + private Action mCaptureAction; + private Action mViewUiAutomatorHierarchyAction; + private Action mSystraceAction; + private Action mUpdateThreadAction; + private Action mUpdateHeapAction; + private Action mGcAction; + private Action mKillAppAction; + private Action mDebugAction; + private Action mHprofAction; + private Action mTracingAction; + + private ImageDescriptor mTracingStartImage; + private ImageDescriptor mTracingStopImage; + + public class HProfHandler extends BaseFileHandler implements IHprofDumpHandler { + public final static String ACTION_SAVE = "hprof.save"; //$NON-NLS-1$ + public final static String ACTION_OPEN = "hprof.open"; //$NON-NLS-1$ + + public final static String DOT_HPROF = ".hprof"; //$NON-NLS-1$ + + HProfHandler(Shell parentShell) { + super(parentShell); + } + + @Override + protected String getDialogTitle() { + return Messages.DeviceView_HPROF_Error; + } + + @Override + public void onEndFailure(final Client client, final String message) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + try { + displayErrorFromUiThread(Messages.DeviceView_Unable_Create_HPROF_For_Application, client + .getClientData().getClientDescription(), message != null ? message + "\n\n" : ""); //$NON-NLS-1$ //$NON-NLS-2$ + } finally { + // this will make sure the dump hprof button is + // re-enabled for the + // current selection. as the client is finished dumping + // an hprof file + doSelectionChanged(mDeviceList.getSelectedClient()); + } + } + }); + } + + @Override + public void onSuccess(final String remoteFilePath, final Client client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + final IDevice device = client.getDevice(); + try { + // get the sync service to pull the HPROF file + final SyncService sync = client.getDevice().getSyncService(); + if (sync != null) { + // get from the preference what action to take + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); + + if (ACTION_OPEN.equals(value)) { + File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ + final String tempPath = temp.getAbsolutePath(); + SyncProgressHelper.run(new SyncRunnable() { + + @Override + public void run(ISyncProgressMonitor monitor) throws SyncException, IOException, + TimeoutException { + sync.pullFile(remoteFilePath, tempPath, monitor); + } + + @Override + public void close() { + sync.close(); + } + }, String.format(Messages.DeviceView_Pulling_From_Device, remoteFilePath), mParentShell); + + open(tempPath); + } else { + // default action is ACTION_SAVE + promptAndPull(sync, client.getClientData().getClientDescription() + DOT_HPROF, + remoteFilePath, Messages.DeviceView_Save_HPROF_File); + + } + } else { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_First_Message, + device.getSerialNumber()); + } + } catch (SyncException e) { + if (e.wasCanceled() == false) { + displayErrorFromUiThread(Messages.DeviceView_Unable_Download_HPROF_From_Device_Two_Param, + device.getSerialNumber(), e.getMessage()); + } + } catch (Exception e) { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_Second_Message, + device.getSerialNumber()); + + } finally { + // this will make sure the dump hprof button is + // re-enabled for the + // current selection. as the client is finished dumping + // an hprof file + doSelectionChanged(mDeviceList.getSelectedClient()); + } + } + }); + } + + @Override + public void onSuccess(final byte[] data, final Client client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + // get from the preference what action to take + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); + + if (ACTION_OPEN.equals(value)) { + try { + // no need to give an extension since we're going to + // convert the + // file anyway after. + File tempFile = saveTempFile(data, null /* extension */); + open(tempFile.getAbsolutePath()); + } catch (Exception e) { + String errorMsg = e.getMessage(); + displayErrorFromUiThread(Messages.DeviceView_Failed_To_Save_HPROF_Data, + errorMsg != null ? ":\n" + errorMsg : "."); //$NON-NLS-1$ //$NON-NLS-2$ + } + } else { + // default action is ACTION_SAVE + promptAndSave(client.getClientData().getClientDescription() + DOT_HPROF, data, + Messages.DeviceView_Save_HPROF_File); + } + } + }); + } + + private void open(String path) throws IOException, InterruptedException, PartInitException { + // make a temp file to convert the hprof into something + // readable by normal tools + File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ + String tempPath = temp.getAbsolutePath(); + + String[] command = new String[3]; + command[0] = DdmsPlugin.getHprofConverter(); + command[1] = path; + command[2] = tempPath; + + Process p = Runtime.getRuntime().exec(command); + p.waitFor(); + + IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(tempPath)); + if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { + // before we open the file in an editor window, we make sure the + // current + // workbench page has an editor area (typically the ddms + // perspective doesn't). + IWorkbench workbench = PlatformUI.getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + if (page == null) { + return; + } + + if (page.isEditorAreaVisible() == false) { + IAdaptable input; + input = page.getInput(); + try { + workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", //$NON-NLS-1$ + window, input); + } catch (WorkbenchException e) { + } + } + + IDE.openEditorOnFileStore(page, fileStore); + } + } + } + + public DeviceView() { + // the view is declared with allowMultiple="false" so we + // can safely do this. + sThis = this; + } + + public static DeviceView getInstance() { + return sThis; + } + + @Override + public void createPartControl(Composite parent) { + mParentShell = parent.getShell(); + + ImageFactory imageFactory = DdmsPlugin.getDefault().getImageFactory(); + + mDeviceList = new DevicePanel(USE_SELECTED_DEBUG_PORT, imageFactory); + mDeviceList.createPanel(parent); + mDeviceList.addSelectionListener(this); + + DdmsPlugin plugin = DdmsPlugin.getDefault(); + mDeviceList.addSelectionListener(plugin); + plugin.setListeningState(true); + + mCaptureAction = new Action(Messages.DeviceView_Screen_Capture) { + @Override + public void run() { + ScreenShotDialog dlg = new ScreenShotDialog(DdmsPlugin.getDisplay().getActiveShell()); + dlg.open(mDeviceList.getSelectedDevice()); + } + }; + mCaptureAction.setToolTipText(Messages.DeviceView_Screen_Capture_Tooltip); + mCaptureAction.setImageDescriptor(imageFactory.getDescriptorByName("capture.png")); //$NON-NLS-1$ + + mViewUiAutomatorHierarchyAction = new Action("Dump View Hierarchy for UI Automator") { + @Override + public void run() { + takeUiAutomatorSnapshot(mDeviceList.getSelectedDevice(), DdmsPlugin.getDisplay().getActiveShell()); + } + }; + mViewUiAutomatorHierarchyAction.setToolTipText("Dump View Hierarchy for UI Automator"); + mViewUiAutomatorHierarchyAction.setImageDescriptor(DdmsPlugin.getImageDescriptor("icons/uiautomator.png")); //$NON-NLS-1$ + + mSystraceAction = new Action("Capture System Wide Trace") { + @Override + public void run() { + launchSystrace(mDeviceList.getSelectedDevice(), DdmsPlugin.getDisplay().getActiveShell()); + } + }; + mSystraceAction.setToolTipText("Capture system wide trace using Android systrace"); + mSystraceAction.setImageDescriptor(DdmsPlugin.getImageDescriptor("icons/systrace.png")); //$NON-NLS-1$ + mSystraceAction.setEnabled(true); + + mResetAdbAction = new Action(Messages.DeviceView_Reset_ADB) { + @Override + public void run() { + AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); + if (bridge != null) { + if (bridge.restart() == false) { + // get the current Display + final Display display = DdmsPlugin.getDisplay(); + + // dialog box only run in ui thread.. + display.asyncExec(new Runnable() { + @Override + public void run() { + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, Messages.DeviceView_ADB_Error, + Messages.DeviceView_ADB_Failed_Restart); + } + }); + } + } + } + }; + mResetAdbAction.setToolTipText(Messages.DeviceView_Reset_ADB_Host_Deamon); + mResetAdbAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() + .getImageDescriptor(ISharedImages.IMG_OBJS_WARN_TSK)); + + mKillAppAction = new Action() { + @Override + public void run() { + mDeviceList.killSelectedClient(); + } + }; + + mKillAppAction.setText(Messages.DeviceView_Stop_Process); + mKillAppAction.setToolTipText(Messages.DeviceView_Stop_Process_Tooltip); + mKillAppAction.setImageDescriptor(imageFactory.getDescriptorByName(DevicePanel.ICON_HALT)); + + mGcAction = new Action() { + @Override + public void run() { + mDeviceList.forceGcOnSelectedClient(); + } + }; + + mGcAction.setText(Messages.DeviceView_Cause_GC); + mGcAction.setToolTipText(Messages.DeviceView_Cause_GC_Tooltip); + mGcAction.setImageDescriptor(imageFactory.getDescriptorByName(DevicePanel.ICON_GC)); + + mHprofAction = new Action() { + @Override + public void run() { + mDeviceList.dumpHprof(); + doSelectionChanged(mDeviceList.getSelectedClient()); + } + }; + mHprofAction.setText(Messages.DeviceView_Dump_HPROF_File); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Tooltip); + mHprofAction.setImageDescriptor(imageFactory.getDescriptorByName(DevicePanel.ICON_HPROF)); + + mUpdateHeapAction = new Action(Messages.DeviceView_Update_Heap, IAction.AS_CHECK_BOX) { + @Override + public void run() { + boolean enable = mUpdateHeapAction.isChecked(); + mDeviceList.setEnabledHeapOnSelectedClient(enable); + } + }; + mUpdateHeapAction.setToolTipText(Messages.DeviceView_Update_Heap_Tooltip); + mUpdateHeapAction.setImageDescriptor(imageFactory.getDescriptorByName(DevicePanel.ICON_HEAP)); + + mUpdateThreadAction = new Action(Messages.DeviceView_Threads, IAction.AS_CHECK_BOX) { + @Override + public void run() { + boolean enable = mUpdateThreadAction.isChecked(); + mDeviceList.setEnabledThreadOnSelectedClient(enable); + } + }; + mUpdateThreadAction.setToolTipText(Messages.DeviceView_Threads_Tooltip); + mUpdateThreadAction.setImageDescriptor(imageFactory.getDescriptorByName(DevicePanel.ICON_THREAD)); + + mTracingAction = new Action() { + @Override + public void run() { + mDeviceList.toggleMethodProfiling(); + } + }; + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingStartImage = imageFactory.getDescriptorByName(DevicePanel.ICON_TRACING_START); + mTracingStopImage = imageFactory.getDescriptorByName(DevicePanel.ICON_TRACING_STOP); + mTracingAction.setImageDescriptor(mTracingStartImage); + + mDebugAction = new Action(Messages.DeviceView_Debug_Process) { + @Override + public void run() { + if (DdmsPlugin.getDefault().hasDebuggerConnectors()) { + Client currentClient = mDeviceList.getSelectedClient(); + if (currentClient != null) { + ClientData clientData = currentClient.getClientData(); + + // make sure the client can be debugged + switch (clientData.getDebuggerConnectionStatus()) { + case ERROR: { + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, + Messages.DeviceView_Process_Debug_Already_In_Use); + return; + } + case ATTACHED: { + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, + Messages.DeviceView_Process_Already_Being_Debugged); + return; + } + } + + // get the name of the client + String packageName = clientData.getClientDescription(); + if (packageName != null) { + + // try all connectors till one returns true. + IDebuggerConnector[] connectors = DdmsPlugin.getDefault().getDebuggerConnectors(); + + if (connectors != null) { + for (IDebuggerConnector connector : connectors) { + try { + if (connector.connectDebugger(packageName, + currentClient.getDebuggerListenPort(), + DdmPreferences.getSelectedDebugPort())) { + return; + } + } catch (Throwable t) { + // ignore, we'll just not use this + // implementation + } + } + } + + // if we get to this point, then we failed to find a + // project + // that matched the application to debug + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title, + String.format(Messages.DeviceView_Debug_Session_Failed, packageName)); + } + } + } + } + }; + mDebugAction.setToolTipText(Messages.DeviceView_Debug_Process_Tooltip); + mDebugAction.setImageDescriptor(imageFactory.getDescriptorByName("debug-attach.png")); //$NON-NLS-1$ + mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors()); + + placeActions(); + + // disabling all action buttons + selectionChanged(null, null); + + ClientData.setHprofDumpHandler(new HProfHandler(mParentShell)); + AndroidDebugBridge.addClientChangeListener(this); + ClientData.setMethodProfilingHandler(new MethodProfilingHandler(mParentShell) { + @Override + protected void open(String tempPath) { + if (DdmsPlugin.getDefault().launchTraceview(tempPath) == false) { + super.open(tempPath); + } + } + }); + } + + private void takeUiAutomatorSnapshot(final IDevice device, final Shell shell) { + ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); + try { + dialog.run(true, false, new IRunnableWithProgress() { + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + UiAutomatorResult result = null; + try { + result = UiAutomatorHelper.takeSnapshot(device, monitor); + } catch (UiAutomatorException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + } + + UiAutomatorViewer.openEditor(result); + } + }); + } catch (Exception e) { + Throwable t = e; + if (e instanceof InvocationTargetException) { + t = ((InvocationTargetException) e).getTargetException(); + } + Status s = new Status(IStatus.ERROR, DdmsPlugin.PLUGIN_ID, "Error obtaining UI hierarchy", t); + ErrorDialog.openError(shell, "UI Automator", "Unexpected error while obtaining UI hierarchy", s); + } + }; + + private void launchSystrace(final IDevice device, final Shell parentShell) { + final File systraceAssets = new File(DdmsPlugin.getPlatformToolsFolder(), "systrace"); //$NON-NLS-1$ + if (!systraceAssets.isDirectory()) { + MessageDialog.openError(parentShell, "Systrace", + "Updated version of platform-tools (18.0.1 or greater) is required.\n" + + "Please update your platform-tools using SDK Manager."); + return; + } + + SystraceVersionDetector detector = new SystraceVersionDetector(device); + try { + new ProgressMonitorDialog(parentShell).run(true, false, detector); + } catch (InvocationTargetException e) { + MessageDialog.openError(parentShell, "Systrace", "Unexpected error while detecting atrace version: " + e); + return; + } catch (InterruptedException e) { + return; + } + + final ISystraceOptionsDialog dlg; + if (detector.getVersion() == SystraceVersionDetector.SYSTRACE_V1) { + dlg = new SystraceOptionsDialogV1(parentShell); + } else { + Client[] clients = device.getClients(); + List apps = new ArrayList(clients.length); + for (int i = 0; i < clients.length; i++) { + String name = clients[i].getClientData().getClientDescription(); + if (name != null && !name.isEmpty()) { + apps.add(name); + } + } + dlg = new SystraceOptionsDialogV2(parentShell, detector.getTags(), apps); + } + + if (dlg.open() != Window.OK) { + return; + } + + final ISystraceOptions options = dlg.getSystraceOptions(); + + // set trace tag if necessary: + // adb shell setprop debug.atrace.tags.enableflags + String tag = options.getTags(); + if (tag != null) { + CountDownLatch setTagLatch = new CountDownLatch(1); + CollectingOutputReceiver receiver = new CollectingOutputReceiver(setTagLatch); + try { + String cmd = "setprop debug.atrace.tags.enableflags " + tag; + device.executeShellCommand(cmd, receiver); + setTagLatch.await(5, TimeUnit.SECONDS); + } catch (Exception e) { + MessageDialog.openError(parentShell, "Systrace", "Unexpected error while setting trace tags: " + e); + return; + } + + String shellOutput = receiver.getOutput(); + if (shellOutput.contains("Error type")) { //$NON-NLS-1$ + throw new RuntimeException(receiver.getOutput()); + } + } + + // obtain the output of "adb shell atrace " and generate + // the html file + ProgressMonitorDialog d = new ProgressMonitorDialog(parentShell); + try { + d.run(true, true, new IRunnableWithProgress() { + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + boolean COMPRESS_DATA = true; + + monitor.setTaskName("Collecting Trace Information"); + final String atraceOptions = options.getOptions() + (COMPRESS_DATA ? " -z" : ""); + SystraceTask task = new SystraceTask(device, atraceOptions); + Thread t = new Thread(task, "Systrace Output Receiver"); + t.start(); + + // check if the user has cancelled tracing every so often + while (true) { + t.join(1000); + + if (t.isAlive()) { + if (monitor.isCanceled()) { + task.cancel(); + return; + } + } else { + break; + } + } + + if (task.getError() != null) { + throw new RuntimeException(task.getError()); + } + + monitor.setTaskName("Saving trace information"); + SystraceOutputParser parser = new SystraceOutputParser(COMPRESS_DATA, SystraceOutputParser + .getJs(systraceAssets), SystraceOutputParser.getCss(systraceAssets), SystraceOutputParser + .getHtmlPrefix(systraceAssets), SystraceOutputParser.getHtmlSuffix(systraceAssets)); + + parser.parse(task.getAtraceOutput()); + + String html = parser.getSystraceHtml(); + try { + Files.write(html.getBytes(), new File(dlg.getTraceFilePath())); + } catch (IOException e) { + throw new InvocationTargetException(e); + } + } + }); + } catch (InvocationTargetException e) { + ErrorDialog.openError(parentShell, "Systrace", "Unable to collect system trace.", new Status(IStatus.ERROR, + DdmsPlugin.PLUGIN_ID, "Unexpected error while collecting system trace.", e.getCause())); + } catch (InterruptedException ignore) { + } + } + + @Override + public void setFocus() { + mDeviceList.setFocus(); + } + + /** + * Sent when a new {@link IDevice} and {@link Client} are selected. + * + * @param selectedDevice + * the selected device. If null, no devices are selected. + * @param selectedClient + * The selected client. If null, no clients are selected. + */ + @Override + public void selectionChanged(IDevice selectedDevice, Client selectedClient) { + // update the buttons + doSelectionChanged(selectedClient); + doSelectionChanged(selectedDevice); + } + + private void doSelectionChanged(Client selectedClient) { + // update the buttons + if (selectedClient != null) { + if (USE_SELECTED_DEBUG_PORT) { + // set the client as the debug client + selectedClient.setAsSelectedClient(); + } + + mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors()); + mKillAppAction.setEnabled(true); + mGcAction.setEnabled(true); + + mUpdateHeapAction.setEnabled(true); + mUpdateHeapAction.setChecked(selectedClient.isHeapUpdateEnabled()); + + mUpdateThreadAction.setEnabled(true); + mUpdateThreadAction.setChecked(selectedClient.isThreadUpdateEnabled()); + + ClientData data = selectedClient.getClientData(); + + if (data.hasFeature(ClientData.FEATURE_HPROF)) { + mHprofAction.setEnabled(data.hasPendingHprofDump() == false); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); + } else { + mHprofAction.setEnabled(false); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Not_Supported_By_VM); + } + + if (data.hasFeature(ClientData.FEATURE_PROFILING)) { + mTracingAction.setEnabled(true); + if (data.getMethodProfilingStatus() == MethodProfilingStatus.TRACER_ON + || data.getMethodProfilingStatus() == MethodProfilingStatus.SAMPLER_ON) { + mTracingAction.setToolTipText(Messages.DeviceView_Stop_Method_Profiling_Tooltip); + mTracingAction.setText(Messages.DeviceView_Stop_Method_Profiling); + mTracingAction.setImageDescriptor(mTracingStopImage); + } else { + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + } else { + mTracingAction.setEnabled(false); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Not_Suported_By_Vm); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + } else { + if (USE_SELECTED_DEBUG_PORT) { + // set the client as the debug client + AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); + if (bridge != null) { + bridge.setSelectedClient(null); + } + } + + mDebugAction.setEnabled(false); + mKillAppAction.setEnabled(false); + mGcAction.setEnabled(false); + mUpdateHeapAction.setChecked(false); + mUpdateHeapAction.setEnabled(false); + mUpdateThreadAction.setEnabled(false); + mUpdateThreadAction.setChecked(false); + mHprofAction.setEnabled(false); + + mHprofAction.setEnabled(false); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); + + mTracingAction.setEnabled(false); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + a.selectedClientChanged(selectedClient); + } + } + + private void doSelectionChanged(IDevice selectedDevice) { + boolean validDevice = selectedDevice != null; + + mCaptureAction.setEnabled(validDevice); + mViewUiAutomatorHierarchyAction.setEnabled(validDevice); + mSystraceAction.setEnabled(validDevice); + } + + /** + * Place the actions in the ui. + */ + private final void placeActions() { + IActionBars actionBars = getViewSite().getActionBars(); + + // first in the menu + IMenuManager menuManager = actionBars.getMenuManager(); + menuManager.removeAll(); + menuManager.add(mDebugAction); + menuManager.add(new Separator()); + menuManager.add(mUpdateHeapAction); + menuManager.add(mHprofAction); + menuManager.add(mGcAction); + menuManager.add(new Separator()); + menuManager.add(mUpdateThreadAction); + menuManager.add(mTracingAction); + menuManager.add(new Separator()); + menuManager.add(mKillAppAction); + menuManager.add(new Separator()); + menuManager.add(mCaptureAction); + menuManager.add(new Separator()); + menuManager.add(mViewUiAutomatorHierarchyAction); + menuManager.add(new Separator()); + menuManager.add(mSystraceAction); + menuManager.add(new Separator()); + menuManager.add(mResetAdbAction); + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + menuManager.add(a.getAction()); + } + + // and then in the toolbar + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + toolBarManager.removeAll(); + toolBarManager.add(mDebugAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mUpdateHeapAction); + toolBarManager.add(mHprofAction); + toolBarManager.add(mGcAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mUpdateThreadAction); + toolBarManager.add(mTracingAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mKillAppAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mCaptureAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mViewUiAutomatorHierarchyAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mSystraceAction); + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + toolBarManager.add(a.getAction()); + } + } + + @Override + public void clientChanged(final Client client, int changeMask) { + if ((changeMask & Client.CHANGE_METHOD_PROFILING_STATUS) == Client.CHANGE_METHOD_PROFILING_STATUS) { + if (mDeviceList.getSelectedClient() == client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + // force refresh of the button enabled state. + doSelectionChanged(client); + } + }); + } + } + } +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EmulatorControlView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EmulatorControlView.java index 73d72625..098d491a 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EmulatorControlView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EmulatorControlView.java @@ -1,41 +1,42 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmuilib.EmulatorControlPanel; - -import org.eclipse.swt.widgets.Composite; - -public class EmulatorControlView extends SelectionDependentViewPart { - - public static final String ID = "org.eclipse.andmore.ddms.views.EmulatorControlView"; //$NON-NLS-1$ - - private EmulatorControlPanel mPanel; - - @Override - public void createPartControl(Composite parent) { - mPanel = new EmulatorControlPanel(); - mPanel.createPanel(parent); - setSelectionDependentPanel(mPanel); - } - - @Override - public void setFocus() { - mPanel.setFocus(); - } - -} +/* + * 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmuilib.EmulatorControlPanel; + +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.swt.widgets.Composite; + +public class EmulatorControlView extends SelectionDependentViewPart { + + public static final String ID = "org.eclipse.andmore.ddms.views.EmulatorControlView"; //$NON-NLS-1$ + + private EmulatorControlPanel mPanel; + + @Override + public void createPartControl(Composite parent) { + mPanel = new EmulatorControlPanel(DdmsPlugin.getDefault().getImageFactory()); + mPanel.createPanel(parent); + setSelectionDependentPanel(mPanel); + } + + @Override + public void setFocus() { + mPanel.setFocus(); + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EventLogView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EventLogView.java index f7260b11..c5166602 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EventLogView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/EventLogView.java @@ -1,110 +1,111 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmuilib.ImageLoader; -import com.android.ddmuilib.log.event.EventLogPanel; - -import org.eclipse.andmore.ddms.CommonAction; -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.IActionBars; - -public class EventLogView extends SelectionDependentViewPart { - - private EventLogPanel mLogPanel; - - @Override - public void createPartControl(Composite parent) { - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - - // create the external actions - CommonAction optionsAction = new CommonAction(Messages.EventLogView_Options); - optionsAction.setToolTipText(Messages.EventLogView_Opens_Options_Panel); - optionsAction.setImageDescriptor(loader.loadDescriptor("edit.png")); //$NON-NLS-1$ - - CommonAction clearLogAction = new CommonAction(Messages.EventLogView_Clear_Log); - clearLogAction.setToolTipText(Messages.EventLogView_Clears_Event_Log); - clearLogAction.setImageDescriptor(loader.loadDescriptor("clear.png")); //$NON-NLS-1$ - - CommonAction saveAction = new CommonAction(Messages.EventLogView_Save_Log); - saveAction.setToolTipText(Messages.EventLogView_Saves_Event_Log); - saveAction.setImageDescriptor(loader.loadDescriptor("save.png")); //$NON-NLS-1$ - - CommonAction loadAction = new CommonAction(Messages.EventLogView_Load_Log); - loadAction.setToolTipText(Messages.EventLogView_Loads_Event_Log); - loadAction.setImageDescriptor(loader.loadDescriptor("load.png")); //$NON-NLS-1$ - - CommonAction importBugAction = new CommonAction(Messages.EventLogView_Import_Bug_Report_Log); - importBugAction.setToolTipText(Messages.EventLogView_Imports_Bug_Report); - importBugAction.setImageDescriptor(loader.loadDescriptor("importBug.png")); //$NON-NLS-1$ - - placeActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction); - - mLogPanel = new EventLogPanel(); - mLogPanel.setActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction); - mLogPanel.createPanel(parent); - setSelectionDependentPanel(mLogPanel); - } - - @Override - public void setFocus() { - mLogPanel.setFocus(); - } - - @Override - public void dispose() { - if (mLogPanel != null) { - mLogPanel.stopEventLog(true); - } - } - - /** - * Places the actions in the toolbar and in the menu. - * - * @param importBugAction - */ - private void placeActions(IAction optionAction, IAction clearAction, IAction saveAction, IAction loadAction, - CommonAction importBugAction) { - IActionBars actionBars = getViewSite().getActionBars(); - - // first in the menu - IMenuManager menuManager = actionBars.getMenuManager(); - menuManager.add(clearAction); - menuManager.add(new Separator()); - menuManager.add(saveAction); - menuManager.add(loadAction); - menuManager.add(importBugAction); - menuManager.add(new Separator()); - menuManager.add(optionAction); - - // and then in the toolbar - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - toolBarManager.add(clearAction); - toolBarManager.add(new Separator()); - toolBarManager.add(saveAction); - toolBarManager.add(loadAction); - toolBarManager.add(importBugAction); - toolBarManager.add(new Separator()); - toolBarManager.add(optionAction); - } - -} +/* + * 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmuilib.log.event.EventLogPanel; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.ddms.CommonAction; +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; + +public class EventLogView extends SelectionDependentViewPart { + + private EventLogPanel mLogPanel; + + @Override + public void createPartControl(Composite parent) { + ImageFactory imageFactory = DdmsPlugin.getDefault().getImageFactory(); + + // create the external actions + CommonAction optionsAction = new CommonAction(Messages.EventLogView_Options); + optionsAction.setToolTipText(Messages.EventLogView_Opens_Options_Panel); + optionsAction.setImageDescriptor(imageFactory.getDescriptorByName("edit.png")); //$NON-NLS-1$ + + CommonAction clearLogAction = new CommonAction(Messages.EventLogView_Clear_Log); + clearLogAction.setToolTipText(Messages.EventLogView_Clears_Event_Log); + clearLogAction.setImageDescriptor(imageFactory.getDescriptorByName("clear.png")); //$NON-NLS-1$ + + CommonAction saveAction = new CommonAction(Messages.EventLogView_Save_Log); + saveAction.setToolTipText(Messages.EventLogView_Saves_Event_Log); + saveAction.setImageDescriptor(imageFactory.getDescriptorByName("save.png")); //$NON-NLS-1$ + + CommonAction loadAction = new CommonAction(Messages.EventLogView_Load_Log); + loadAction.setToolTipText(Messages.EventLogView_Loads_Event_Log); + loadAction.setImageDescriptor(imageFactory.getDescriptorByName("load.png")); //$NON-NLS-1$ + + CommonAction importBugAction = new CommonAction(Messages.EventLogView_Import_Bug_Report_Log); + importBugAction.setToolTipText(Messages.EventLogView_Imports_Bug_Report); + importBugAction.setImageDescriptor(imageFactory.getDescriptorByName("importBug.png")); //$NON-NLS-1$ + + placeActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction); + + mLogPanel = new EventLogPanel(imageFactory); + mLogPanel.setActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction); + mLogPanel.createPanel(parent); + setSelectionDependentPanel(mLogPanel); + } + + @Override + public void setFocus() { + mLogPanel.setFocus(); + } + + @Override + public void dispose() { + if (mLogPanel != null) { + mLogPanel.stopEventLog(true); + } + } + + /** + * Places the actions in the toolbar and in the menu. + * + * @param importBugAction + */ + private void placeActions(IAction optionAction, IAction clearAction, IAction saveAction, IAction loadAction, + CommonAction importBugAction) { + IActionBars actionBars = getViewSite().getActionBars(); + + // first in the menu + IMenuManager menuManager = actionBars.getMenuManager(); + menuManager.add(clearAction); + menuManager.add(new Separator()); + menuManager.add(saveAction); + menuManager.add(loadAction); + menuManager.add(importBugAction); + menuManager.add(new Separator()); + menuManager.add(optionAction); + + // and then in the toolbar + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + toolBarManager.add(clearAction); + toolBarManager.add(new Separator()); + toolBarManager.add(saveAction); + toolBarManager.add(loadAction); + toolBarManager.add(importBugAction); + toolBarManager.add(new Separator()); + toolBarManager.add(optionAction); + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/FileExplorerView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/FileExplorerView.java index 93cb09a3..afeb8884 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/FileExplorerView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/FileExplorerView.java @@ -1,177 +1,177 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.ddmuilib.ImageLoader; -import com.android.ddmuilib.explorer.DeviceExplorer; - -import org.eclipse.andmore.ddms.CommonAction; -import org.eclipse.andmore.ddms.DdmsPlugin; -import org.eclipse.andmore.ddms.DdmsPlugin.ISelectionListener; -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.swt.graphics.Device; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.ViewPart; - -public class FileExplorerView extends ViewPart implements ISelectionListener { - - public static final String ID = "org.eclipse.andmore.ddms.views.FileExplorerView"; //$NON-NLS-1$ - - private final static String COLUMN_NAME = DdmsPlugin.PLUGIN_ID + ".explorer.name"; //$NON-NLS-1S - private final static String COLUMN_SIZE = DdmsPlugin.PLUGIN_ID + ".explorer.size"; //$NON-NLS-1S - private final static String COLUMN_DATE = DdmsPlugin.PLUGIN_ID + ".explorer.data"; //$NON-NLS-1S - private final static String COLUMN_TIME = DdmsPlugin.PLUGIN_ID + ".explorer.time"; //$NON-NLS-1S - private final static String COLUMN_PERMISSIONS = DdmsPlugin.PLUGIN_ID + ".explorer.permissions"; //$NON-NLS-1S - private final static String COLUMN_INFO = DdmsPlugin.PLUGIN_ID + ".explorer.info"; //$NON-NLS-1$ - - private DeviceExplorer mExplorer; - - public FileExplorerView() { - } - - @Override - public void createPartControl(Composite parent) { - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - - DeviceExplorer.COLUMN_NAME = COLUMN_NAME; - DeviceExplorer.COLUMN_SIZE = COLUMN_SIZE; - DeviceExplorer.COLUMN_DATE = COLUMN_DATE; - DeviceExplorer.COLUMN_TIME = COLUMN_TIME; - DeviceExplorer.COLUMN_PERMISSIONS = COLUMN_PERMISSIONS; - DeviceExplorer.COLUMN_INFO = COLUMN_INFO; - - // device explorer - mExplorer = new DeviceExplorer(); - - mExplorer.setCustomImages(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE), - PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER), null /* - * apk - * image - */, PlatformUI - .getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT)); - - // creates the actions - CommonAction pushAction = new CommonAction(Messages.FileExplorerView_Push_File) { - @Override - public void run() { - mExplorer.pushIntoSelection(); - } - }; - pushAction.setToolTipText(Messages.FileExplorerView_Push_File_Onto_Device); - pushAction.setImageDescriptor(loader.loadDescriptor("push.png")); //$NON-NLS-1$ - pushAction.setEnabled(false); - - CommonAction pullAction = new CommonAction(Messages.FileExplorerView_Pull_File) { - @Override - public void run() { - mExplorer.pullSelection(); - } - }; - pullAction.setToolTipText(Messages.FileExplorerView_Pull_File_From_File); - pullAction.setImageDescriptor(loader.loadDescriptor("pull.png")); //$NON-NLS-1$ - pullAction.setEnabled(false); - - CommonAction deleteAction = new CommonAction(Messages.FileExplorerView_Delete) { - @Override - public void run() { - mExplorer.deleteSelection(); - } - }; - deleteAction.setToolTipText(Messages.FileExplorerView_Delete_The_Selection); - deleteAction.setImageDescriptor(loader.loadDescriptor("delete.png")); //$NON-NLS-1$ - deleteAction.setEnabled(false); - - CommonAction createNewFolderAction = new CommonAction("New Folder") { - @Override - public void run() { - mExplorer.createNewFolderInSelection(); - } - }; - createNewFolderAction.setToolTipText("New Folder"); - createNewFolderAction.setImageDescriptor(loader.loadDescriptor("add.png")); //$NON-NLS-1$ - createNewFolderAction.setEnabled(false); - - // set up the actions in the explorer - mExplorer.setActions(pushAction, pullAction, deleteAction, createNewFolderAction); - - // and in the ui - IActionBars actionBars = getViewSite().getActionBars(); - IMenuManager menuManager = actionBars.getMenuManager(); - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - - menuManager.add(pullAction); - menuManager.add(pushAction); - menuManager.add(new Separator()); - menuManager.add(deleteAction); - menuManager.add(new Separator()); - menuManager.add(createNewFolderAction); - - toolBarManager.add(pullAction); - toolBarManager.add(pushAction); - toolBarManager.add(new Separator()); - toolBarManager.add(deleteAction); - toolBarManager.add(new Separator()); - toolBarManager.add(createNewFolderAction); - - mExplorer.createPanel(parent); - - DdmsPlugin.getDefault().addSelectionListener(this); - } - - @Override - public void setFocus() { - mExplorer.setFocus(); - } - - /** - * Sent when a new {@link Client} is selected. - * - * @param selectedClient - * The selected client. - */ - @Override - public void selectionChanged(Client selectedClient) { - // pass - } - - /** - * Sent when a new {@link Device} is selected. - * - * @param selectedDevice - * the selected device. - */ - @Override - public void selectionChanged(IDevice selectedDevice) { - mExplorer.switchDevice(selectedDevice); - } - - /** - * Sent when there is no current selection. - */ - public void selectionRemoved() { - - } - -} +/* + * 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmlib.Client; +import com.android.ddmlib.IDevice; +import com.android.ddmuilib.explorer.DeviceExplorer; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.ddms.CommonAction; +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.andmore.ddms.DdmsPlugin.ISelectionListener; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; + +public class FileExplorerView extends ViewPart implements ISelectionListener { + + public static final String ID = "org.eclipse.andmore.ddms.views.FileExplorerView"; //$NON-NLS-1$ + + private final static String COLUMN_NAME = DdmsPlugin.PLUGIN_ID + ".explorer.name"; //$NON-NLS-1S + private final static String COLUMN_SIZE = DdmsPlugin.PLUGIN_ID + ".explorer.size"; //$NON-NLS-1S + private final static String COLUMN_DATE = DdmsPlugin.PLUGIN_ID + ".explorer.data"; //$NON-NLS-1S + private final static String COLUMN_TIME = DdmsPlugin.PLUGIN_ID + ".explorer.time"; //$NON-NLS-1S + private final static String COLUMN_PERMISSIONS = DdmsPlugin.PLUGIN_ID + ".explorer.permissions"; //$NON-NLS-1S + private final static String COLUMN_INFO = DdmsPlugin.PLUGIN_ID + ".explorer.info"; //$NON-NLS-1$ + + private DeviceExplorer mExplorer; + + public FileExplorerView() { + } + + @Override + public void createPartControl(Composite parent) { + ImageFactory imageFactory = DdmsPlugin.getDefault().getImageFactory(); + + DeviceExplorer.COLUMN_NAME = COLUMN_NAME; + DeviceExplorer.COLUMN_SIZE = COLUMN_SIZE; + DeviceExplorer.COLUMN_DATE = COLUMN_DATE; + DeviceExplorer.COLUMN_TIME = COLUMN_TIME; + DeviceExplorer.COLUMN_PERMISSIONS = COLUMN_PERMISSIONS; + DeviceExplorer.COLUMN_INFO = COLUMN_INFO; + + // device explorer + mExplorer = new DeviceExplorer(imageFactory); + + mExplorer.setCustomImages(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE), + PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER), null /* + * apk + * image + */, PlatformUI + .getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT)); + + // creates the actions + CommonAction pushAction = new CommonAction(Messages.FileExplorerView_Push_File) { + @Override + public void run() { + mExplorer.pushIntoSelection(); + } + }; + pushAction.setToolTipText(Messages.FileExplorerView_Push_File_Onto_Device); + pushAction.setImageDescriptor(imageFactory.getDescriptorByName("push.png")); //$NON-NLS-1$ + pushAction.setEnabled(false); + + CommonAction pullAction = new CommonAction(Messages.FileExplorerView_Pull_File) { + @Override + public void run() { + mExplorer.pullSelection(); + } + }; + pullAction.setToolTipText(Messages.FileExplorerView_Pull_File_From_File); + pullAction.setImageDescriptor(imageFactory.getDescriptorByName("pull.png")); //$NON-NLS-1$ + pullAction.setEnabled(false); + + CommonAction deleteAction = new CommonAction(Messages.FileExplorerView_Delete) { + @Override + public void run() { + mExplorer.deleteSelection(); + } + }; + deleteAction.setToolTipText(Messages.FileExplorerView_Delete_The_Selection); + deleteAction.setImageDescriptor(imageFactory.getDescriptorByName("delete.png")); //$NON-NLS-1$ + deleteAction.setEnabled(false); + + CommonAction createNewFolderAction = new CommonAction("New Folder") { + @Override + public void run() { + mExplorer.createNewFolderInSelection(); + } + }; + createNewFolderAction.setToolTipText("New Folder"); + createNewFolderAction.setImageDescriptor(imageFactory.getDescriptorByName("add.png")); //$NON-NLS-1$ + createNewFolderAction.setEnabled(false); + + // set up the actions in the explorer + mExplorer.setActions(pushAction, pullAction, deleteAction, createNewFolderAction); + + // and in the ui + IActionBars actionBars = getViewSite().getActionBars(); + IMenuManager menuManager = actionBars.getMenuManager(); + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + + menuManager.add(pullAction); + menuManager.add(pushAction); + menuManager.add(new Separator()); + menuManager.add(deleteAction); + menuManager.add(new Separator()); + menuManager.add(createNewFolderAction); + + toolBarManager.add(pullAction); + toolBarManager.add(pushAction); + toolBarManager.add(new Separator()); + toolBarManager.add(deleteAction); + toolBarManager.add(new Separator()); + toolBarManager.add(createNewFolderAction); + + mExplorer.createPanel(parent); + + DdmsPlugin.getDefault().addSelectionListener(this); + } + + @Override + public void setFocus() { + mExplorer.setFocus(); + } + + /** + * Sent when a new {@link Client} is selected. + * + * @param selectedClient + * The selected client. + */ + @Override + public void selectionChanged(Client selectedClient) { + // pass + } + + /** + * Sent when a new {@link Device} is selected. + * + * @param selectedDevice + * the selected device. + */ + @Override + public void selectionChanged(IDevice selectedDevice) { + mExplorer.switchDevice(selectedDevice); + } + + /** + * Sent when there is no current selection. + */ + public void selectionRemoved() { + + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/LogCatView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/LogCatView.java index 78573463..9c374237 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/LogCatView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/LogCatView.java @@ -1,115 +1,115 @@ -/* - * Copyright (C) 2011 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmlib.logcat.LogCatMessage; -import com.android.ddmuilib.logcat.ILogCatMessageSelectionListener; -import com.android.ddmuilib.logcat.LogCatPanel; -import com.android.ddmuilib.logcat.LogCatStackTraceParser; - -import org.eclipse.andmore.ddms.DdmsPlugin; -import org.eclipse.andmore.ddms.JavaSourceRevealer; -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.actions.ActionFactory; - -public class LogCatView extends SelectionDependentViewPart { - /** LogCatView ID as defined in plugin.xml. */ - public static final String ID = "org.eclipse.andmore.ddms.views.LogCatView"; //$NON-NLS-1$ - - /** Switch perspective when a Java file is opened from logcat view. */ - public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; - - /** Target perspective to open when a Java file is opened from logcat view. */ - public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ - - private LogCatPanel mLogCatPanel; - private LogCatStackTraceParser mStackTraceParser = new LogCatStackTraceParser(); - - private Clipboard mClipboard; - - @Override - public void createPartControl(Composite parent) { - parent.setLayout(new FillLayout()); - - IPreferenceStore prefStore = DdmsPlugin.getDefault().getPreferenceStore(); - mLogCatPanel = new LogCatPanel(prefStore); - mLogCatPanel.createPanel(parent); - setSelectionDependentPanel(mLogCatPanel); - - mLogCatPanel.addLogCatMessageSelectionListener(new ILogCatMessageSelectionListener() { - @Override - public void messageDoubleClicked(LogCatMessage m) { - onDoubleClick(m); - } - }); - - mClipboard = new Clipboard(parent.getDisplay()); - IActionBars actionBars = getViewSite().getActionBars(); - actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action(Messages.LogCatView_Copy) { - @Override - public void run() { - mLogCatPanel.copySelectionToClipboard(mClipboard); - } - }); - - actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action(Messages.LogCatView_Select_All) { - @Override - public void run() { - mLogCatPanel.selectAll(); - } - }); - - actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), new Action("Find") { - @Override - public void run() { - mLogCatPanel.showFindDialog(); - } - }); - } - - @Override - public void setFocus() { - } - - private void onDoubleClick(LogCatMessage m) { - String msg = m.getMessage(); - if (!mStackTraceParser.isValidExceptionTrace(msg)) { - return; - } - - IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); - String perspectiveId = null; - if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { - perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); - } - - String fileName = mStackTraceParser.getFileName(msg); - int lineNumber = mStackTraceParser.getLineNumber(msg); - String methodName = mStackTraceParser.getMethodName(msg); - JavaSourceRevealer.revealMethod(methodName, fileName, lineNumber, perspectiveId); - } - - public void selectTransientAppFilter(String appName) { - mLogCatPanel.selectTransientAppFilter(appName); - } -} +/* + * Copyright (C) 2011 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 org.eclipse.andmore.ddms.views; + +import com.android.ddmlib.logcat.LogCatMessage; +import com.android.ddmuilib.logcat.ILogCatMessageSelectionListener; +import com.android.ddmuilib.logcat.LogCatPanel; +import com.android.ddmuilib.logcat.LogCatStackTraceParser; + +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.andmore.ddms.JavaSourceRevealer; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.andmore.ddms.preferences.PreferenceInitializer; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.actions.ActionFactory; + +public class LogCatView extends SelectionDependentViewPart { + /** LogCatView ID as defined in plugin.xml. */ + public static final String ID = "org.eclipse.andmore.ddms.views.LogCatView"; //$NON-NLS-1$ + + /** Switch perspective when a Java file is opened from logcat view. */ + public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; + + /** Target perspective to open when a Java file is opened from logcat view. */ + public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ + + private LogCatPanel mLogCatPanel; + private LogCatStackTraceParser mStackTraceParser = new LogCatStackTraceParser(); + + private Clipboard mClipboard; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new FillLayout()); + + IPreferenceStore prefStore = DdmsPlugin.getDefault().getPreferenceStore(); + mLogCatPanel = new LogCatPanel(prefStore, DdmsPlugin.getDefault().getImageFactory()); + mLogCatPanel.createPanel(parent); + setSelectionDependentPanel(mLogCatPanel); + + mLogCatPanel.addLogCatMessageSelectionListener(new ILogCatMessageSelectionListener() { + @Override + public void messageDoubleClicked(LogCatMessage m) { + onDoubleClick(m); + } + }); + + mClipboard = new Clipboard(parent.getDisplay()); + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action(Messages.LogCatView_Copy) { + @Override + public void run() { + mLogCatPanel.copySelectionToClipboard(mClipboard); + } + }); + + actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action(Messages.LogCatView_Select_All) { + @Override + public void run() { + mLogCatPanel.selectAll(); + } + }); + + actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), new Action("Find") { + @Override + public void run() { + mLogCatPanel.showFindDialog(); + } + }); + } + + @Override + public void setFocus() { + } + + private void onDoubleClick(LogCatMessage m) { + String msg = m.getMessage(); + if (!mStackTraceParser.isValidExceptionTrace(msg)) { + return; + } + + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String perspectiveId = null; + if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { + perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); + } + + String fileName = mStackTraceParser.getFileName(msg); + int lineNumber = mStackTraceParser.getLineNumber(msg); + String methodName = mStackTraceParser.getMethodName(msg); + JavaSourceRevealer.revealMethod(methodName, fileName, lineNumber, perspectiveId); + } + + public void selectTransientAppFilter(String appName) { + mLogCatPanel.selectTransientAppFilter(appName); + } +} diff --git a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/OldLogCatView.java b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/OldLogCatView.java index 4a4b5c16..51a7bb54 100644 --- a/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/OldLogCatView.java +++ b/android-core/plugins/org.eclipse.andmore.ddms/src/org/eclipse/andmore/ddms/views/OldLogCatView.java @@ -1,371 +1,371 @@ -/* - * 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 org.eclipse.andmore.ddms.views; - -import com.android.ddmlib.Log.LogLevel; -import com.android.ddmuilib.ImageLoader; -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.ddmuilib.logcat.LogPanel.LogCatViewInterface; - -import org.eclipse.andmore.ddms.CommonAction; -import org.eclipse.andmore.ddms.DdmsPlugin; -import org.eclipse.andmore.ddms.i18n.Messages; -import org.eclipse.andmore.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.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -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.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.ide.IDE; - -import java.util.ArrayList; - -/** - * The log cat view displays log output from the current device selection. - */ -public final class OldLogCatView extends SelectionDependentViewPart implements LogCatViewInterface { - - public static final String ID = "org.eclipse.andmore.ddms.views.OldLogCatView"; //$NON-NLS-1$ - - private static final String PREFS_COL_TIME = DdmsPlugin.PLUGIN_ID + ".logcat.time"; //$NON-NLS-1$ - private static final String PREFS_COL_LEVEL = DdmsPlugin.PLUGIN_ID + ".logcat.level"; //$NON-NLS-1$ - private static final String PREFS_COL_PID = DdmsPlugin.PLUGIN_ID + ".logcat.pid"; //$NON-NLS-1$ - private static final String PREFS_COL_TAG = DdmsPlugin.PLUGIN_ID + ".logcat.tag"; //$NON-NLS-1$ - private static final String PREFS_COL_MESSAGE = DdmsPlugin.PLUGIN_ID + ".logcat.message"; //$NON-NLS-1$ - - private static final String PREFS_FILTERS = DdmsPlugin.PLUGIN_ID + ".logcat.filters"; //$NON-NLS-1$ - - public static final String CHOICE_METHOD_DECLARATION = DdmsPlugin.PLUGIN_ID + ".logcat.MethodDeclaration"; //$NON-NLS-1$ - public static final String CHOICE_ERROR_LINE = DdmsPlugin.PLUGIN_ID + ".logcat.ErrorLine"; //$NON-NLS-1$ - - /* Default values for the switch of perspective. */ - public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; - public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ - private static OldLogCatView sThis; - private LogPanel mLogPanel; - - private CommonAction mCreateFilterAction; - private CommonAction mDeleteFilterAction; - private CommonAction mEditFilterAction; - private CommonAction mExportAction; - - private CommonAction[] mLogLevelActions; - private String[] mLogLevelIcons = { "v.png", //$NON-NLS-1S - "d.png", //$NON-NLS-1S - "i.png", //$NON-NLS-1S - "w.png", //$NON-NLS-1S - "e.png", //$NON-NLS-1S - }; - - private Action mClearAction; - - private Clipboard mClipboard; - - /** - * An implementation of {@link ILogFilterStorageManager} to bridge to the - * eclipse preference store, and saves the log filters. - */ - private final class FilterStorage implements ILogFilterStorageManager { - - @Override - public LogFilter[] getFilterFromStore() { - String filterPrefs = DdmsPlugin.getDefault().getPreferenceStore().getString(PREFS_FILTERS); - - // split in a string per filter - String[] filters = filterPrefs.split("\\|"); //$NON-NLS-1$ - - ArrayList list = new ArrayList(filters.length); - - for (String f : filters) { - if (f.length() > 0) { - LogFilter logFilter = new LogFilter(); - if (logFilter.loadFromString(f)) { - list.add(logFilter); - } - } - } - - return list.toArray(new LogFilter[list.size()]); - } - - @Override - public void saveFilters(LogFilter[] filters) { - StringBuilder sb = new StringBuilder(); - for (LogFilter f : filters) { - String filterString = f.toString(); - sb.append(filterString); - sb.append('|'); - } - - DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS, sb.toString()); - } - - @Override - public boolean requiresDefaultFilter() { - return true; - } - } - - public OldLogCatView() { - sThis = this; - LogPanel.PREFS_TIME = PREFS_COL_TIME; - LogPanel.PREFS_LEVEL = PREFS_COL_LEVEL; - LogPanel.PREFS_PID = PREFS_COL_PID; - LogPanel.PREFS_TAG = PREFS_COL_TAG; - LogPanel.PREFS_MESSAGE = PREFS_COL_MESSAGE; - } - - /** - * Returns the singleton instance. - */ - public static OldLogCatView getInstance() { - return sThis; - } - - /** - * Sets the display font. - * - * @param font - * The font. - */ - public static void setFont(Font font) { - if (sThis != null && sThis.mLogPanel != null) { - sThis.mLogPanel.setFont(font); - } - } - - @Override - public void createPartControl(Composite parent) { - Display d = parent.getDisplay(); - LogColors colors = new LogColors(); - - ImageLoader loader = ImageLoader.getDdmUiLibLoader(); - - colors.infoColor = new Color(d, 0, 127, 0); - colors.debugColor = new Color(d, 0, 0, 127); - colors.errorColor = new Color(d, 255, 0, 0); - colors.warningColor = new Color(d, 255, 127, 0); - colors.verboseColor = new Color(d, 0, 0, 0); - - mCreateFilterAction = new CommonAction(Messages.LogCatView_Create_Filter) { - @Override - public void run() { - mLogPanel.addFilter(); - } - }; - mCreateFilterAction.setToolTipText(Messages.LogCatView_Create_Filter_Tooltip); - mCreateFilterAction.setImageDescriptor(loader.loadDescriptor("add.png")); //$NON-NLS-1$ - - mEditFilterAction = new CommonAction(Messages.LogCatView_Edit_Filter) { - @Override - public void run() { - mLogPanel.editFilter(); - } - }; - mEditFilterAction.setToolTipText(Messages.LogCatView_Edit_Filter_Tooltip); - mEditFilterAction.setImageDescriptor(loader.loadDescriptor("edit.png")); //$NON-NLS-1$ - - mDeleteFilterAction = new CommonAction(Messages.LogCatView_Delete_Filter) { - @Override - public void run() { - mLogPanel.deleteFilter(); - } - }; - mDeleteFilterAction.setToolTipText(Messages.LogCatView_Delete_Filter_Tooltip); - mDeleteFilterAction.setImageDescriptor(loader.loadDescriptor("delete.png")); //$NON-NLS-1$ - - mExportAction = new CommonAction(Messages.LogCatView_Export_Selection_As_Text) { - @Override - public void run() { - mLogPanel.save(); - } - }; - mExportAction.setToolTipText(Messages.LogCatView_Export_Selection_As_Text_Tooltip); - mExportAction.setImageDescriptor(loader.loadDescriptor("save.png")); //$NON-NLS-1$ - - LogLevel[] levels = LogLevel.values(); - mLogLevelActions = new CommonAction[mLogLevelIcons.length]; - for (int i = 0; i < mLogLevelActions.length; i++) { - String name = levels[i].getStringValue(); - mLogLevelActions[i] = new CommonAction(name, IAction.AS_CHECK_BOX) { - @Override - public void run() { - // disable the other actions and record current index - for (int j = 0; j < mLogLevelActions.length; j++) { - Action a = mLogLevelActions[j]; - if (a == this) { - a.setChecked(true); - - // set the log level - mLogPanel.setCurrentFilterLogLevel(j + 2); - } else { - a.setChecked(false); - } - } - } - }; - - mLogLevelActions[i].setToolTipText(name); - mLogLevelActions[i].setImageDescriptor(loader.loadDescriptor(mLogLevelIcons[i])); - } - - mClearAction = new Action(Messages.LogCatView_Clear_Log) { - @Override - public void run() { - mLogPanel.clear(); - } - }; - mClearAction.setImageDescriptor(loader.loadDescriptor("clear.png")); //$NON-NLS-1$ - - // now create the log view - mLogPanel = new LogPanel(colors, new FilterStorage(), LogPanel.FILTER_MANUAL); - mLogPanel.setLogCatViewInterface(this); - mLogPanel.setActions(mDeleteFilterAction, mEditFilterAction, mLogLevelActions); - - // get the font - String fontStr = DdmsPlugin.getDefault().getPreferenceStore().getString(PreferenceInitializer.ATTR_LOGCAT_FONT); - if (fontStr != null) { - FontData data = new FontData(fontStr); - - if (fontStr != null) { - mLogPanel.setFont(new Font(parent.getDisplay(), data)); - } - } - - mLogPanel.createPanel(parent); - setSelectionDependentPanel(mLogPanel); - - // place the actions. - placeActions(); - - // setup the copy action - mClipboard = new Clipboard(d); - IActionBars actionBars = getViewSite().getActionBars(); - actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action(Messages.LogCatView_Copy) { - @Override - public void run() { - mLogPanel.copy(mClipboard); - } - }); - - // setup the select all action - actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action(Messages.LogCatView_Select_All) { - @Override - public void run() { - mLogPanel.selectAll(); - } - }); - } - - @Override - public void dispose() { - mLogPanel.stopLogCat(true); - mClipboard.dispose(); - } - - @Override - public void setFocus() { - mLogPanel.setFocus(); - } - - /** - * Place the actions in the ui. - */ - private void placeActions() { - IActionBars actionBars = getViewSite().getActionBars(); - - // first in the menu - IMenuManager menuManager = actionBars.getMenuManager(); - menuManager.add(mCreateFilterAction); - menuManager.add(mEditFilterAction); - menuManager.add(mDeleteFilterAction); - menuManager.add(new Separator()); - menuManager.add(mClearAction); - menuManager.add(new Separator()); - menuManager.add(mExportAction); - - // and then in the toolbar - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - for (CommonAction a : mLogLevelActions) { - toolBarManager.add(a); - } - toolBarManager.add(new Separator()); - toolBarManager.add(mCreateFilterAction); - toolBarManager.add(mEditFilterAction); - toolBarManager.add(mDeleteFilterAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mClearAction); - } - - 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(IStatus.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e); - DdmsPlugin.getDefault().getLog().log(s); - } - } - - void switchPerspective() { - IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); - if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { - IWorkbench workbench = PlatformUI.getWorkbench(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - IPerspectiveRegistry perspectiveRegistry = workbench.getPerspectiveRegistry(); - String perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); - if (perspectiveId != null && perspectiveId.length() > 0 - && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) { - try { - workbench.showPerspective(perspectiveId, window); - } catch (WorkbenchException e) { - e.printStackTrace(); - } - } - } - } - - @Override - public void onDoubleClick() { - } -} +/* + * 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 org.eclipse.andmore.ddms.views; + +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.ddmuilib.logcat.LogPanel.LogCatViewInterface; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.ddms.CommonAction; +import org.eclipse.andmore.ddms.DdmsPlugin; +import org.eclipse.andmore.ddms.i18n.Messages; +import org.eclipse.andmore.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.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +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.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.ide.IDE; + +import java.util.ArrayList; + +/** + * The log cat view displays log output from the current device selection. + */ +public final class OldLogCatView extends SelectionDependentViewPart implements LogCatViewInterface { + + public static final String ID = "org.eclipse.andmore.ddms.views.OldLogCatView"; //$NON-NLS-1$ + + private static final String PREFS_COL_TIME = DdmsPlugin.PLUGIN_ID + ".logcat.time"; //$NON-NLS-1$ + private static final String PREFS_COL_LEVEL = DdmsPlugin.PLUGIN_ID + ".logcat.level"; //$NON-NLS-1$ + private static final String PREFS_COL_PID = DdmsPlugin.PLUGIN_ID + ".logcat.pid"; //$NON-NLS-1$ + private static final String PREFS_COL_TAG = DdmsPlugin.PLUGIN_ID + ".logcat.tag"; //$NON-NLS-1$ + private static final String PREFS_COL_MESSAGE = DdmsPlugin.PLUGIN_ID + ".logcat.message"; //$NON-NLS-1$ + + private static final String PREFS_FILTERS = DdmsPlugin.PLUGIN_ID + ".logcat.filters"; //$NON-NLS-1$ + + public static final String CHOICE_METHOD_DECLARATION = DdmsPlugin.PLUGIN_ID + ".logcat.MethodDeclaration"; //$NON-NLS-1$ + public static final String CHOICE_ERROR_LINE = DdmsPlugin.PLUGIN_ID + ".logcat.ErrorLine"; //$NON-NLS-1$ + + /* Default values for the switch of perspective. */ + public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; + public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ + private static OldLogCatView sThis; + private LogPanel mLogPanel; + + private CommonAction mCreateFilterAction; + private CommonAction mDeleteFilterAction; + private CommonAction mEditFilterAction; + private CommonAction mExportAction; + + private CommonAction[] mLogLevelActions; + private String[] mLogLevelIcons = { "v.png", //$NON-NLS-1S + "d.png", //$NON-NLS-1S + "i.png", //$NON-NLS-1S + "w.png", //$NON-NLS-1S + "e.png", //$NON-NLS-1S + }; + + private Action mClearAction; + private ImageFactory mImageFactory; + private Clipboard mClipboard; + + /** + * An implementation of {@link ILogFilterStorageManager} to bridge to the + * eclipse preference store, and saves the log filters. + */ + private final class FilterStorage implements ILogFilterStorageManager { + + @Override + public LogFilter[] getFilterFromStore() { + String filterPrefs = DdmsPlugin.getDefault().getPreferenceStore().getString(PREFS_FILTERS); + + // split in a string per filter + String[] filters = filterPrefs.split("\\|"); //$NON-NLS-1$ + + ArrayList list = new ArrayList(filters.length); + + for (String f : filters) { + if (f.length() > 0) { + LogFilter logFilter = new LogFilter(); + if (logFilter.loadFromString(f)) { + list.add(logFilter); + } + } + } + + return list.toArray(new LogFilter[list.size()]); + } + + @Override + public void saveFilters(LogFilter[] filters) { + StringBuilder sb = new StringBuilder(); + for (LogFilter f : filters) { + String filterString = f.toString(); + sb.append(filterString); + sb.append('|'); + } + + DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS, sb.toString()); + } + + @Override + public boolean requiresDefaultFilter() { + return true; + } + } + + public OldLogCatView(ImageFactory imageFactory) { + sThis = this; + mImageFactory = imageFactory; + LogPanel.PREFS_TIME = PREFS_COL_TIME; + LogPanel.PREFS_LEVEL = PREFS_COL_LEVEL; + LogPanel.PREFS_PID = PREFS_COL_PID; + LogPanel.PREFS_TAG = PREFS_COL_TAG; + LogPanel.PREFS_MESSAGE = PREFS_COL_MESSAGE; + } + + /** + * Returns the singleton instance. + */ + public static OldLogCatView getInstance() { + return sThis; + } + + /** + * Sets the display font. + * + * @param font + * The font. + */ + public static void setFont(Font font) { + if (sThis != null && sThis.mLogPanel != null) { + sThis.mLogPanel.setFont(font); + } + } + + @Override + public void createPartControl(Composite parent) { + Display d = parent.getDisplay(); + LogColors colors = new LogColors(); + + ImageFactory imageFactory = DdmsPlugin.getDefault().getImageFactory(); + colors.infoColor = new Color(d, 0, 127, 0); + colors.debugColor = new Color(d, 0, 0, 127); + colors.errorColor = new Color(d, 255, 0, 0); + colors.warningColor = new Color(d, 255, 127, 0); + colors.verboseColor = new Color(d, 0, 0, 0); + + mCreateFilterAction = new CommonAction(Messages.LogCatView_Create_Filter) { + @Override + public void run() { + mLogPanel.addFilter(); + } + }; + mCreateFilterAction.setToolTipText(Messages.LogCatView_Create_Filter_Tooltip); + mCreateFilterAction.setImageDescriptor(imageFactory.getDescriptorByName("add.png")); //$NON-NLS-1$ + + mEditFilterAction = new CommonAction(Messages.LogCatView_Edit_Filter) { + @Override + public void run() { + mLogPanel.editFilter(); + } + }; + mEditFilterAction.setToolTipText(Messages.LogCatView_Edit_Filter_Tooltip); + mEditFilterAction.setImageDescriptor(imageFactory.getDescriptorByName("edit.png")); //$NON-NLS-1$ + + mDeleteFilterAction = new CommonAction(Messages.LogCatView_Delete_Filter) { + @Override + public void run() { + mLogPanel.deleteFilter(); + } + }; + mDeleteFilterAction.setToolTipText(Messages.LogCatView_Delete_Filter_Tooltip); + mDeleteFilterAction.setImageDescriptor(imageFactory.getDescriptorByName("delete.png")); //$NON-NLS-1$ + + mExportAction = new CommonAction(Messages.LogCatView_Export_Selection_As_Text) { + @Override + public void run() { + mLogPanel.save(); + } + }; + mExportAction.setToolTipText(Messages.LogCatView_Export_Selection_As_Text_Tooltip); + mExportAction.setImageDescriptor(imageFactory.getDescriptorByName("save.png")); //$NON-NLS-1$ + + LogLevel[] levels = LogLevel.values(); + mLogLevelActions = new CommonAction[mLogLevelIcons.length]; + for (int i = 0; i < mLogLevelActions.length; i++) { + String name = levels[i].getStringValue(); + mLogLevelActions[i] = new CommonAction(name, IAction.AS_CHECK_BOX) { + @Override + public void run() { + // disable the other actions and record current index + for (int j = 0; j < mLogLevelActions.length; j++) { + Action a = mLogLevelActions[j]; + if (a == this) { + a.setChecked(true); + + // set the log level + mLogPanel.setCurrentFilterLogLevel(j + 2); + } else { + a.setChecked(false); + } + } + } + }; + + mLogLevelActions[i].setToolTipText(name); + mLogLevelActions[i].setImageDescriptor(imageFactory.getDescriptorByName(mLogLevelIcons[i])); + } + + mClearAction = new Action(Messages.LogCatView_Clear_Log) { + @Override + public void run() { + mLogPanel.clear(); + } + }; + mClearAction.setImageDescriptor(imageFactory.getDescriptorByName("clear.png")); //$NON-NLS-1$ + + // now create the log view + mLogPanel = new LogPanel(colors, new FilterStorage(), LogPanel.FILTER_MANUAL, mImageFactory); + mLogPanel.setLogCatViewInterface(this); + mLogPanel.setActions(mDeleteFilterAction, mEditFilterAction, mLogLevelActions); + + // get the font + String fontStr = DdmsPlugin.getDefault().getPreferenceStore().getString(PreferenceInitializer.ATTR_LOGCAT_FONT); + if (fontStr != null) { + FontData data = new FontData(fontStr); + + if (fontStr != null) { + mLogPanel.setFont(new Font(parent.getDisplay(), data)); + } + } + + mLogPanel.createPanel(parent); + setSelectionDependentPanel(mLogPanel); + + // place the actions. + placeActions(); + + // setup the copy action + mClipboard = new Clipboard(d); + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action(Messages.LogCatView_Copy) { + @Override + public void run() { + mLogPanel.copy(mClipboard); + } + }); + + // setup the select all action + actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action(Messages.LogCatView_Select_All) { + @Override + public void run() { + mLogPanel.selectAll(); + } + }); + } + + @Override + public void dispose() { + mLogPanel.stopLogCat(true); + mClipboard.dispose(); + } + + @Override + public void setFocus() { + mLogPanel.setFocus(); + } + + /** + * Place the actions in the ui. + */ + private void placeActions() { + IActionBars actionBars = getViewSite().getActionBars(); + + // first in the menu + IMenuManager menuManager = actionBars.getMenuManager(); + menuManager.add(mCreateFilterAction); + menuManager.add(mEditFilterAction); + menuManager.add(mDeleteFilterAction); + menuManager.add(new Separator()); + menuManager.add(mClearAction); + menuManager.add(new Separator()); + menuManager.add(mExportAction); + + // and then in the toolbar + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + for (CommonAction a : mLogLevelActions) { + toolBarManager.add(a); + } + toolBarManager.add(new Separator()); + toolBarManager.add(mCreateFilterAction); + toolBarManager.add(mEditFilterAction); + toolBarManager.add(mDeleteFilterAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mClearAction); + } + + 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(IStatus.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e); + DdmsPlugin.getDefault().getLog().log(s); + } + } + + void switchPerspective() { + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { + IWorkbench workbench = PlatformUI.getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IPerspectiveRegistry perspectiveRegistry = workbench.getPerspectiveRegistry(); + String perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); + if (perspectiveId != null && perspectiveId.length() > 0 + && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) { + try { + workbench.showPerspective(perspectiveId, window); + } catch (WorkbenchException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void onDoubleClick() { + } +} diff --git a/android-core/plugins/org.eclipse.andmore.gldebugger.tests/.classpath b/android-core/plugins/org.eclipse.andmore.gldebugger.tests/.classpath index 2abf4833..0c695ecb 100644 --- a/android-core/plugins/org.eclipse.andmore.gldebugger.tests/.classpath +++ b/android-core/plugins/org.eclipse.andmore.gldebugger.tests/.classpath @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.gldebugger/.classpath b/android-core/plugins/org.eclipse.andmore.gldebugger/.classpath index 2edb66f5..da24a626 100755 --- a/android-core/plugins/org.eclipse.andmore.gldebugger/.classpath +++ b/android-core/plugins/org.eclipse.andmore.gldebugger/.classpath @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.gldebugger/.settings/org.eclipse.jdt.core.prefs b/android-core/plugins/org.eclipse.andmore.gldebugger/.settings/org.eclipse.jdt.core.prefs index ea661960..c137e176 100644 --- a/android-core/plugins/org.eclipse.andmore.gldebugger/.settings/org.eclipse.jdt.core.prefs +++ b/android-core/plugins/org.eclipse.andmore.gldebugger/.settings/org.eclipse.jdt.core.prefs @@ -1,98 +1,98 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled +org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/android-core/plugins/org.eclipse.andmore.gldebugger/META-INF/MANIFEST.MF b/android-core/plugins/org.eclipse.andmore.gldebugger/META-INF/MANIFEST.MF index 1d210493..d766990e 100644 --- a/android-core/plugins/org.eclipse.andmore.gldebugger/META-INF/MANIFEST.MF +++ b/android-core/plugins/org.eclipse.andmore.gldebugger/META-INF/MANIFEST.MF @@ -1,23 +1,24 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Tracer for OpenGL ES -Bundle-SymbolicName: org.eclipse.andmore.gldebugger;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.gltrace.GlTracePlugin -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.ui.ide, - org.eclipse.core.resources, - org.eclipse.core.filesystem, - org.eclipse.ui.console, - org.eclipse.andmore.ddms, - org.eclipse.andmore.base -Bundle-ActivationPolicy: lazy -Bundle-ClassPath: libs/host-libprotobuf-java-2.3.0-lite.jar, - libs/liblzf-1.0.jar, - . -Bundle-Vendor: Eclipse Andmore -Export-Package: org.eclipse.andmore.gltrace;x-friends:="com.android.ide.eclipse.gldebugger.tests", - org.eclipse.andmore.gltrace.format;x-friends:="com.android.ide.eclipse.gldebugger.tests", - org.eclipse.andmore.gltrace.model;x-friends:="com.android.ide.eclipse.gldebugger.tests" -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tracer for OpenGL ES +Bundle-SymbolicName: org.eclipse.andmore.gldebugger;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.gltrace.GlTracePlugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ui.ide, + org.eclipse.core.resources, + org.eclipse.core.filesystem, + org.eclipse.ui.console, + org.eclipse.andmore.swt, + org.eclipse.andmore.ddms, + org.eclipse.andmore.ddmuilib;bundle-version="0.5.2" +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: libs/host-libprotobuf-java-2.3.0-lite.jar, + libs/liblzf-1.0.jar, + . +Bundle-Vendor: Eclipse Andmore +Export-Package: org.eclipse.andmore.gltrace;x-friends:="com.android.ide.eclipse.gldebugger.tests", + org.eclipse.andmore.gltrace.format;x-friends:="com.android.ide.eclipse.gldebugger.tests", + org.eclipse.andmore.gltrace.model;x-friends:="com.android.ide.eclipse.gldebugger.tests" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.classpath b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.classpath index 3d094dff..7498423d 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.classpath +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.classpath @@ -1,8 +1,7 @@ - - - - - - - - + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.settings/org.eclipse.jdt.core.prefs b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.settings/org.eclipse.jdt.core.prefs index ea661960..c137e176 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.settings/org.eclipse.jdt.core.prefs +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/.settings/org.eclipse.jdt.core.prefs @@ -1,98 +1,98 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled +org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/META-INF/MANIFEST.MF b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/META-INF/MANIFEST.MF index 8067225a..df622fd1 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/META-INF/MANIFEST.MF +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/META-INF/MANIFEST.MF @@ -1,18 +1,19 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: %pluginName -Bundle-SymbolicName: org.eclipse.andmore.hierarchyviewer;singleton:=true -Bundle-Version: 0.5.2.qualifier -Bundle-Activator: org.eclipse.andmore.hierarchyviewer.HierarchyViewerPlugin -Bundle-Vendor: %providerName -Bundle-Localization: plugin -Bundle-ActivationPolicy: lazy -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.ui.console, - org.eclipse.andmore.ddms, - org.eclipse.andmore.base -Bundle-ClassPath: ., - libs/hierarchyviewer2lib.jar -Export-Package: org.eclipse.andmore.hierarchyviewer -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.andmore.hierarchyviewer;singleton:=true +Bundle-Version: 0.5.2.qualifier +Bundle-Activator: org.eclipse.andmore.hierarchyviewer.HierarchyViewerPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ui.console, + org.eclipse.andmore.swt, + org.eclipse.andmore.ddms, + org.eclipse.andmore.hierarchyviewer2lib, + org.eclipse.andmore.ddmuilib +Bundle-ClassPath: . +Export-Package: org.eclipse.andmore.hierarchyviewer +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/build.properties b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/build.properties index 9fb508f2..7e5f633d 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/build.properties +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/build.properties @@ -1,11 +1,12 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - icons/,\ - plugin.xml,\ - .,\ - libs/,\ - about.html,\ - about.ini,\ - about.properties,\ - plugin.properties +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + icons/,\ + plugin.xml,\ + .,\ + libs/,\ + about.html,\ + about.ini,\ + about.properties,\ + plugin.properties,\ + hiarch/ diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/auto-refresh.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/auto-refresh.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/auto-refresh.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/auto-refresh.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/capture-psd.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/capture-psd.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/capture-psd.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/capture-psd.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/device-view-selected.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device-view-selected.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/device-view-selected.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device-view-selected.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/device-view.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device-view.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/device-view.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device-view.png diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device.png new file mode 100644 index 00000000..7dbbbb6a Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/device.png differ diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/display.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/display.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/display.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/display.png diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/emulator.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/emulator.png new file mode 100644 index 00000000..a7180428 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/emulator.png differ diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/file.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/file.png new file mode 100644 index 00000000..043a8143 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/file.png differ diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/filtered.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/filtered.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/filtered.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/filtered.png diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/folder.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/folder.png new file mode 100644 index 00000000..7e29b1a4 Binary files /dev/null and b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/folder.png differ diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/green.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/green.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/green.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/green.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/inspect-screenshot.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/inspect-screenshot.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/inspect-screenshot.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/inspect-screenshot.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/invalidate.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/invalidate.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/invalidate.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/invalidate.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-all-views.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-all-views.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-all-views.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-all-views.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-overlay.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-overlay.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-overlay.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-overlay.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-view-hierarchy.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-view-hierarchy.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/load-view-hierarchy.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/load-view-hierarchy.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/not-selected.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/not-selected.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/not-selected.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/not-selected.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/on-black.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/on-black.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/on-black.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/on-black.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/on-white.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/on-white.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/on-white.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/on-white.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/picker.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/picker.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/picker.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/picker.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/pixel-perfect-view-selected.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/pixel-perfect-view-selected.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/pixel-perfect-view-selected.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/pixel-perfect-view-selected.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/pixel-perfect-view.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/pixel-perfect-view.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/pixel-perfect-view.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/pixel-perfect-view.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/profile.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/profile.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/profile.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/profile.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/red.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/red.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/red.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/red.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/refresh-windows.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/refresh-windows.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/refresh-windows.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/refresh-windows.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/request-layout.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/request-layout.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/request-layout.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/request-layout.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/save.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/save.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/save.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/save.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/sdk-hierarchyviewer-128.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/sdk-hierarchyviewer-128.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/sdk-hierarchyviewer-128.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/sdk-hierarchyviewer-128.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/sdk-hierarchyviewer-16.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/sdk-hierarchyviewer-16.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/sdk-hierarchyviewer-16.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/sdk-hierarchyviewer-16.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-filtered-small.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-filtered-small.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-filtered-small.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-filtered-small.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-filtered.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-filtered.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-filtered.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-filtered.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-small.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-small.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected-small.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected-small.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/selected.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/selected.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/show-extras.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/show-extras.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/show-extras.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/show-extras.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/show-overlay.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/show-overlay.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/show-overlay.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/show-overlay.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/tree-view-selected.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/tree-view-selected.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/tree-view-selected.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/tree-view-selected.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/tree-view.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/tree-view.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/tree-view.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/tree-view.png diff --git a/andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/yellow.png b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/yellow.png similarity index 100% rename from andmore-swt/org.eclipse.andmore.hierarchyviewer2lib/src/main/java/images/yellow.png rename to android-core/plugins/org.eclipse.andmore.hierarchyviewer/hiarch/icons/yellow.png diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/libs/hierarchyviewer2lib.jar b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/libs/hierarchyviewer2lib.jar deleted file mode 100644 index a339050e..00000000 Binary files a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/libs/hierarchyviewer2lib.jar and /dev/null differ diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HiarchResourceProvider.java b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HiarchResourceProvider.java new file mode 100644 index 00000000..f237555e --- /dev/null +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HiarchResourceProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 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 org.eclipse.andmore.hierarchyviewer; + +import org.eclipse.andmore.base.resources.PluginResourceProvider; +import org.eclipse.jface.resource.ImageDescriptor; + +public class HiarchResourceProvider implements PluginResourceProvider { + + @Override + public ImageDescriptor descriptorFromPath(String imagePath) { + return HierarchyViewerPlugin.getImageDescriptor("hiarch/" + imagePath); + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPlugin.java b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPlugin.java index 01fa81ae..b26adc1b 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPlugin.java +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPlugin.java @@ -24,6 +24,7 @@ import com.android.hierarchyviewerlib.HierarchyViewerDirector; import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; @@ -82,7 +83,7 @@ public void run() { }); // set up the ddms log to use the ddms console. - Log.setLogOutput(new ILogOutput() { + Log.addLogger(new ILogOutput() { @Override public void printLog(LogLevel logLevel, String tag, String message) { if (logLevel.getPriority() >= LogLevel.ERROR.getPriority()) { @@ -164,6 +165,13 @@ public static HierarchyViewerPlugin getPlugin() { return sPlugin; } + /** + * Returns an image descriptor for the image file at the given plug-in + * relative path + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } /** * Prints a message, associated with a project to the specified stream * diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPluginDirector.java b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPluginDirector.java index e6f36fde..c3c953d0 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPluginDirector.java +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/HierarchyViewerPluginDirector.java @@ -1,119 +1,126 @@ -/* - * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer; - -import com.android.hierarchyviewerlib.HierarchyViewerDirector; -import com.android.hierarchyviewerlib.device.IHvDevice; -import com.android.hierarchyviewerlib.models.Window; - -import org.eclipse.andmore.hierarchyviewer.views.PixelPerfectTreeView; -import org.eclipse.andmore.hierarchyviewer.views.PropertyView; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; - -public class HierarchyViewerPluginDirector extends HierarchyViewerDirector { - - public static HierarchyViewerDirector createDirector() { - return sDirector = new HierarchyViewerPluginDirector(); - } - - @Override - public void executeInBackground(final String taskName, final Runnable task) { - Job job = new Job(taskName) { - @Override - protected IStatus run(IProgressMonitor monitor) { - task.run(); - return Status.OK_STATUS; - } - }; - job.setPriority(Job.SHORT); - job.setRule(mSchedulingRule); - job.schedule(); - } - - private ISchedulingRule mSchedulingRule = new ISchedulingRule() { - @Override - public boolean contains(ISchedulingRule rule) { - return rule == this; - } - - @Override - public boolean isConflicting(ISchedulingRule rule) { - return rule == this; - } - - }; - - @Override - public String getAdbLocation() { - return HierarchyViewerPlugin.getPlugin().getPreferenceStore().getString(HierarchyViewerPlugin.ADB_LOCATION); - } - - @Override - public void loadViewTreeData(Window window) { - super.loadViewTreeData(window); - - // The windows tab hides the property tab, so let's bring the property - // tab - // forward. - - IWorkbenchWindow[] windows = HierarchyViewerPlugin.getPlugin().getWorkbench().getWorkbenchWindows(); - for (IWorkbenchWindow currentWindow : windows) { - IWorkbenchPage page = currentWindow.getActivePage(); - if (page.getPerspective().getId().equals(TreeViewPerspective.ID)) { - try { - IWorkbenchPart part = page.findView(PropertyView.ID); - if (part != null) { - page.showView(PropertyView.ID); - } - } catch (PartInitException e) { - - } - } - } - } - - @Override - public void loadPixelPerfectData(IHvDevice device) { - super.loadPixelPerfectData(device); - - // The windows tab hides the tree tab, so let's bring the tree tab - // forward. - - IWorkbenchWindow[] windows = HierarchyViewerPlugin.getPlugin().getWorkbench().getWorkbenchWindows(); - for (IWorkbenchWindow window : windows) { - IWorkbenchPage page = window.getActivePage(); - if (page.getPerspective().getId().equals(PixelPerfectPespective.ID)) { - try { - IWorkbenchPart part = page.findView(PixelPerfectTreeView.ID); - if (part != null) { - page.showView(PixelPerfectTreeView.ID); - } - } catch (PartInitException e) { - - } - } - } - } -} +/* + * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer; + +import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import com.android.hierarchyviewerlib.device.IHvDevice; +import com.android.hierarchyviewerlib.models.Window; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.andmore.base.resources.JFaceImageLoader; +import org.eclipse.andmore.hierarchyviewer.views.PixelPerfectTreeView; +import org.eclipse.andmore.hierarchyviewer.views.PropertyView; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; + +public class HierarchyViewerPluginDirector extends HierarchyViewerDirector { + + public HierarchyViewerPluginDirector(ImageFactory imageFactory) { + super(imageFactory); + // TODO Auto-generated constructor stub + } + + public static HierarchyViewerDirector createDirector() { + return sDirector = new HierarchyViewerPluginDirector(new JFaceImageLoader(new HiarchResourceProvider())); + } + + @Override + public void executeInBackground(final String taskName, final Runnable task) { + Job job = new Job(taskName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + task.run(); + return Status.OK_STATUS; + } + }; + job.setPriority(Job.SHORT); + job.setRule(mSchedulingRule); + job.schedule(); + } + + private ISchedulingRule mSchedulingRule = new ISchedulingRule() { + @Override + public boolean contains(ISchedulingRule rule) { + return rule == this; + } + + @Override + public boolean isConflicting(ISchedulingRule rule) { + return rule == this; + } + + }; + + @Override + public String getAdbLocation() { + return HierarchyViewerPlugin.getPlugin().getPreferenceStore().getString(HierarchyViewerPlugin.ADB_LOCATION); + } + + @Override + public void loadViewTreeData(Window window) { + super.loadViewTreeData(window); + + // The windows tab hides the property tab, so let's bring the property + // tab + // forward. + + IWorkbenchWindow[] windows = HierarchyViewerPlugin.getPlugin().getWorkbench().getWorkbenchWindows(); + for (IWorkbenchWindow currentWindow : windows) { + IWorkbenchPage page = currentWindow.getActivePage(); + if (page.getPerspective().getId().equals(TreeViewPerspective.ID)) { + try { + IWorkbenchPart part = page.findView(PropertyView.ID); + if (part != null) { + page.showView(PropertyView.ID); + } + } catch (PartInitException e) { + + } + } + } + } + + @Override + public void loadPixelPerfectData(IHvDevice device) { + super.loadPixelPerfectData(device); + + // The windows tab hides the tree tab, so let's bring the tree tab + // forward. + + IWorkbenchWindow[] windows = HierarchyViewerPlugin.getPlugin().getWorkbench().getWorkbenchWindows(); + for (IWorkbenchWindow window : windows) { + IWorkbenchPage page = window.getActivePage(); + if (page.getPerspective().getId().equals(PixelPerfectPespective.ID)) { + try { + IWorkbenchPart part = page.findView(PixelPerfectTreeView.ID); + if (part != null) { + page.showView(PixelPerfectTreeView.ID); + } + } catch (PartInitException e) { + + } + } + } + } +} diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/LayoutView.java b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/LayoutView.java index c9f6b29a..f19276bd 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/LayoutView.java +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/LayoutView.java @@ -1,160 +1,160 @@ -/* - * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer.views; - -import com.android.ddmuilib.ImageLoader; -import com.android.hierarchyviewerlib.HierarchyViewerDirector; -import com.android.hierarchyviewerlib.models.TreeViewModel; -import com.android.hierarchyviewerlib.models.TreeViewModel.ITreeChangeListener; -import com.android.hierarchyviewerlib.ui.LayoutViewer; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.part.ViewPart; - -public class LayoutView extends ViewPart implements ITreeChangeListener { - - public static final String ID = "org.eclipse.andmore.hierarchyviewer.views.LayoutView"; //$NON-NLS-1$ - - private LayoutViewer mLayoutViewer; - - private Image mOnBlack; - - private Image mOnWhite; - - private Action mShowExtrasAction = new Action("Show &Extras", Action.AS_CHECK_BOX) { - @Override - public void run() { - mLayoutViewer.setShowExtras(isChecked()); - } - }; - - private Action mLoadAllViewsAction = new Action("Load All &Views") { - @Override - public void run() { - HierarchyViewerDirector.getDirector().loadAllViews(); - mShowExtrasAction.setChecked(true); - mLayoutViewer.setShowExtras(true); - } - }; - - private Action mOnBlackWhiteAction = new Action("Change Background &Color") { - @Override - public void run() { - boolean newValue = !mLayoutViewer.getOnBlack(); - mLayoutViewer.setOnBlack(newValue); - if (newValue) { - setImageDescriptor(ImageDescriptor.createFromImage(mOnWhite)); - } else { - setImageDescriptor(ImageDescriptor.createFromImage(mOnBlack)); - } - } - }; - - @Override - public void createPartControl(Composite parent) { - mShowExtrasAction.setAccelerator(SWT.MOD1 + 'E'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - Image image = imageLoader.loadImage("show-extras.png", Display.getDefault()); //$NON-NLS-1$ - mShowExtrasAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); - mShowExtrasAction.setToolTipText("Show images"); - mShowExtrasAction.setEnabled(TreeViewModel.getModel().getTree() != null); - - mOnWhite = imageLoader.loadImage("on-white.png", Display.getDefault()); //$NON-NLS-1$ - mOnBlack = imageLoader.loadImage("on-black.png", Display.getDefault()); //$NON-NLS-1$ - - mOnBlackWhiteAction.setAccelerator(SWT.MOD1 + 'C'); - mOnBlackWhiteAction.setImageDescriptor(ImageDescriptor.createFromImage(mOnWhite)); - mOnBlackWhiteAction.setToolTipText("Change layout viewer background color"); - - mLoadAllViewsAction.setAccelerator(SWT.MOD1 + 'V'); - image = imageLoader.loadImage("load-all-views.png", Display.getDefault()); //$NON-NLS-1$ - mLoadAllViewsAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); - mLoadAllViewsAction.setToolTipText("Load all view images"); - mLoadAllViewsAction.setEnabled(TreeViewModel.getModel().getTree() != null); - - parent.setLayout(new FillLayout()); - - mLayoutViewer = new LayoutViewer(parent); - - placeActions(); - - TreeViewModel.getModel().addTreeChangeListener(this); - } - - public void placeActions() { - IActionBars actionBars = getViewSite().getActionBars(); - - IMenuManager mm = actionBars.getMenuManager(); - mm.removeAll(); - mm.add(mOnBlackWhiteAction); - mm.add(mShowExtrasAction); - mm.add(mLoadAllViewsAction); - - IToolBarManager tm = actionBars.getToolBarManager(); - tm.removeAll(); - tm.add(mOnBlackWhiteAction); - tm.add(mShowExtrasAction); - tm.add(mLoadAllViewsAction); - } - - @Override - public void dispose() { - super.dispose(); - TreeViewModel.getModel().removeTreeChangeListener(this); - } - - @Override - public void setFocus() { - mLayoutViewer.setFocus(); - } - - @Override - public void selectionChanged() { - // pass - } - - @Override - public void treeChanged() { - Display.getDefault().syncExec(new Runnable() { - @Override - public void run() { - mLoadAllViewsAction.setEnabled(TreeViewModel.getModel().getTree() != null); - mShowExtrasAction.setEnabled(TreeViewModel.getModel().getTree() != null); - } - }); - } - - @Override - public void viewportChanged() { - // pass - } - - @Override - public void zoomChanged() { - // pass - } - -} +/* + * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer.views; + +import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import com.android.hierarchyviewerlib.models.TreeViewModel; +import com.android.hierarchyviewerlib.models.TreeViewModel.ITreeChangeListener; +import com.android.hierarchyviewerlib.ui.LayoutViewer; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.part.ViewPart; + +public class LayoutView extends ViewPart implements ITreeChangeListener { + + public static final String ID = "org.eclipse.andmore.hierarchyviewer.views.LayoutView"; //$NON-NLS-1$ + + private LayoutViewer mLayoutViewer; + + private Image mOnBlack; + + private Image mOnWhite; + + private Action mShowExtrasAction = new Action("Show &Extras", Action.AS_CHECK_BOX) { + @Override + public void run() { + mLayoutViewer.setShowExtras(isChecked()); + } + }; + + private Action mLoadAllViewsAction = new Action("Load All &Views") { + @Override + public void run() { + HierarchyViewerDirector.getDirector().loadAllViews(); + mShowExtrasAction.setChecked(true); + mLayoutViewer.setShowExtras(true); + } + }; + + private Action mOnBlackWhiteAction = new Action("Change Background &Color") { + @Override + public void run() { + boolean newValue = !mLayoutViewer.getOnBlack(); + mLayoutViewer.setOnBlack(newValue); + if (newValue) { + setImageDescriptor(ImageDescriptor.createFromImage(mOnWhite)); + } else { + setImageDescriptor(ImageDescriptor.createFromImage(mOnBlack)); + } + } + }; + + @Override + public void createPartControl(Composite parent) { + mShowExtrasAction.setAccelerator(SWT.MOD1 + 'E'); + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + Image image = imageFactory.getImageByName("show-extras.png"); //$NON-NLS-1$ + mShowExtrasAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); + mShowExtrasAction.setToolTipText("Show images"); + mShowExtrasAction.setEnabled(TreeViewModel.getModel().getTree() != null); + + mOnWhite = imageFactory.getImageByName("on-white.png"); //$NON-NLS-1$ + mOnBlack = imageFactory.getImageByName("on-black.png"); //$NON-NLS-1$ + + mOnBlackWhiteAction.setAccelerator(SWT.MOD1 + 'C'); + mOnBlackWhiteAction.setImageDescriptor(ImageDescriptor.createFromImage(mOnWhite)); + mOnBlackWhiteAction.setToolTipText("Change layout viewer background color"); + + mLoadAllViewsAction.setAccelerator(SWT.MOD1 + 'V'); + image = imageFactory.getImageByName("load-all-views.png"); //$NON-NLS-1$ + mLoadAllViewsAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); + mLoadAllViewsAction.setToolTipText("Load all view images"); + mLoadAllViewsAction.setEnabled(TreeViewModel.getModel().getTree() != null); + + parent.setLayout(new FillLayout()); + + mLayoutViewer = new LayoutViewer(parent); + + placeActions(); + + TreeViewModel.getModel().addTreeChangeListener(this); + } + + public void placeActions() { + IActionBars actionBars = getViewSite().getActionBars(); + + IMenuManager mm = actionBars.getMenuManager(); + mm.removeAll(); + mm.add(mOnBlackWhiteAction); + mm.add(mShowExtrasAction); + mm.add(mLoadAllViewsAction); + + IToolBarManager tm = actionBars.getToolBarManager(); + tm.removeAll(); + tm.add(mOnBlackWhiteAction); + tm.add(mShowExtrasAction); + tm.add(mLoadAllViewsAction); + } + + @Override + public void dispose() { + super.dispose(); + TreeViewModel.getModel().removeTreeChangeListener(this); + } + + @Override + public void setFocus() { + mLayoutViewer.setFocus(); + } + + @Override + public void selectionChanged() { + // pass + } + + @Override + public void treeChanged() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + mLoadAllViewsAction.setEnabled(TreeViewModel.getModel().getTree() != null); + mShowExtrasAction.setEnabled(TreeViewModel.getModel().getTree() != null); + } + }); + } + + @Override + public void viewportChanged() { + // pass + } + + @Override + public void zoomChanged() { + // pass + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/PixelPerfectLoupeView.java b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/PixelPerfectLoupeView.java index 583bd0f0..a0d74a58 100644 --- a/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/PixelPerfectLoupeView.java +++ b/android-core/plugins/org.eclipse.andmore.hierarchyviewer/src/org/eclipse/andmore/hierarchyviewer/views/PixelPerfectLoupeView.java @@ -1,164 +1,164 @@ -/* - * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer.views; - -import com.android.ddmuilib.ImageLoader; -import com.android.hierarchyviewerlib.HierarchyViewerDirector; -import com.android.hierarchyviewerlib.actions.PixelPerfectAutoRefreshAction; -import com.android.hierarchyviewerlib.models.PixelPerfectModel; -import com.android.hierarchyviewerlib.models.PixelPerfectModel.IImageChangeListener; -import com.android.hierarchyviewerlib.ui.PixelPerfectControls; -import com.android.hierarchyviewerlib.ui.PixelPerfectLoupe; -import com.android.hierarchyviewerlib.ui.PixelPerfectPixelPanel; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.part.ViewPart; - -public class PixelPerfectLoupeView extends ViewPart implements IImageChangeListener { - - public static final String ID = "org.eclipse.andmore.hierarchyviewer.views.PixelPerfectLoupeView"; //$NON-NLS-1$ - - private PixelPerfectLoupe mPixelPerfectLoupe; - - private Action mShowInLoupeAction = new Action("&Show Overlay", Action.AS_CHECK_BOX) { - @Override - public void run() { - mPixelPerfectLoupe.setShowOverlay(isChecked()); - } - }; - - @Override - public void createPartControl(Composite parent) { - mShowInLoupeAction.setAccelerator(SWT.MOD1 + 'S'); - ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class); - Image image = imageLoader.loadImage("show-overlay.png", Display.getDefault()); //$NON-NLS-1$ - mShowInLoupeAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); - mShowInLoupeAction.setToolTipText("Show the overlay in the loupe view"); - mShowInLoupeAction.setEnabled(PixelPerfectModel.getModel().getOverlayImage() != null); - PixelPerfectModel.getModel().addImageChangeListener(this); - - GridLayout loupeLayout = new GridLayout(); - loupeLayout.marginWidth = loupeLayout.marginHeight = 0; - loupeLayout.horizontalSpacing = loupeLayout.verticalSpacing = 0; - parent.setLayout(loupeLayout); - - Composite pixelPerfectLoupeBorder = new Composite(parent, SWT.BORDER); - pixelPerfectLoupeBorder.setLayoutData(new GridData(GridData.FILL_BOTH)); - GridLayout pixelPerfectLoupeBorderGridLayout = new GridLayout(); - pixelPerfectLoupeBorderGridLayout.marginWidth = pixelPerfectLoupeBorderGridLayout.marginHeight = 0; - pixelPerfectLoupeBorderGridLayout.horizontalSpacing = pixelPerfectLoupeBorderGridLayout.verticalSpacing = 0; - pixelPerfectLoupeBorder.setLayout(pixelPerfectLoupeBorderGridLayout); - - mPixelPerfectLoupe = new PixelPerfectLoupe(pixelPerfectLoupeBorder); - mPixelPerfectLoupe.setLayoutData(new GridData(GridData.FILL_BOTH)); - - PixelPerfectPixelPanel pixelPerfectPixelPanel = new PixelPerfectPixelPanel(pixelPerfectLoupeBorder); - pixelPerfectPixelPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - PixelPerfectControls pixelPerfectControls = new PixelPerfectControls(parent); - pixelPerfectControls.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - placeActions(); - } - - private void placeActions() { - IActionBars actionBars = getViewSite().getActionBars(); - - IMenuManager mm = actionBars.getMenuManager(); - mm.removeAll(); - mm.add(PixelPerfectAutoRefreshAction.getAction()); - mm.add(mShowInLoupeAction); - - IToolBarManager tm = actionBars.getToolBarManager(); - tm.removeAll(); - tm.add(PixelPerfectAutoRefreshAction.getAction()); - tm.add(mShowInLoupeAction); - } - - @Override - public void dispose() { - super.dispose(); - PixelPerfectModel.getModel().removeImageChangeListener(this); - } - - @Override - public void setFocus() { - mPixelPerfectLoupe.setFocus(); - } - - @Override - public void crosshairMoved() { - // pass - } - - @Override - public void treeChanged() { - // pass - } - - @Override - public void imageChanged() { - // pass - } - - @Override - public void imageLoaded() { - Display.getDefault().syncExec(new Runnable() { - @Override - public void run() { - Image overlayImage = PixelPerfectModel.getModel().getOverlayImage(); - mShowInLoupeAction.setEnabled(overlayImage != null); - } - }); - } - - @Override - public void overlayChanged() { - Display.getDefault().syncExec(new Runnable() { - @Override - public void run() { - mShowInLoupeAction.setEnabled(PixelPerfectModel.getModel().getOverlayImage() != null); - } - }); - } - - @Override - public void overlayTransparencyChanged() { - // pass - } - - @Override - public void selectionChanged() { - // pass - } - - @Override - public void zoomChanged() { - // pass - } - -} +/* + * Copyright (C) 2010 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 org.eclipse.andmore.hierarchyviewer.views; + +import com.android.hierarchyviewerlib.HierarchyViewerDirector; +import com.android.hierarchyviewerlib.actions.PixelPerfectAutoRefreshAction; +import com.android.hierarchyviewerlib.models.PixelPerfectModel; +import com.android.hierarchyviewerlib.models.PixelPerfectModel.IImageChangeListener; +import com.android.hierarchyviewerlib.ui.PixelPerfectControls; +import com.android.hierarchyviewerlib.ui.PixelPerfectLoupe; +import com.android.hierarchyviewerlib.ui.PixelPerfectPixelPanel; + +import org.eclipse.andmore.base.resources.ImageFactory; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.part.ViewPart; + +public class PixelPerfectLoupeView extends ViewPart implements IImageChangeListener { + + public static final String ID = "org.eclipse.andmore.hierarchyviewer.views.PixelPerfectLoupeView"; //$NON-NLS-1$ + + private PixelPerfectLoupe mPixelPerfectLoupe; + + private Action mShowInLoupeAction = new Action("&Show Overlay", Action.AS_CHECK_BOX) { + @Override + public void run() { + mPixelPerfectLoupe.setShowOverlay(isChecked()); + } + }; + + @Override + public void createPartControl(Composite parent) { + mShowInLoupeAction.setAccelerator(SWT.MOD1 + 'S'); + ImageFactory imageFactory = HierarchyViewerDirector.getDirector().getImageFactory(); + Image image = imageFactory.getImageByName("show-overlay.png"); //$NON-NLS-1$ + mShowInLoupeAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); + mShowInLoupeAction.setToolTipText("Show the overlay in the loupe view"); + mShowInLoupeAction.setEnabled(PixelPerfectModel.getModel().getOverlayImage() != null); + PixelPerfectModel.getModel().addImageChangeListener(this); + + GridLayout loupeLayout = new GridLayout(); + loupeLayout.marginWidth = loupeLayout.marginHeight = 0; + loupeLayout.horizontalSpacing = loupeLayout.verticalSpacing = 0; + parent.setLayout(loupeLayout); + + Composite pixelPerfectLoupeBorder = new Composite(parent, SWT.BORDER); + pixelPerfectLoupeBorder.setLayoutData(new GridData(GridData.FILL_BOTH)); + GridLayout pixelPerfectLoupeBorderGridLayout = new GridLayout(); + pixelPerfectLoupeBorderGridLayout.marginWidth = pixelPerfectLoupeBorderGridLayout.marginHeight = 0; + pixelPerfectLoupeBorderGridLayout.horizontalSpacing = pixelPerfectLoupeBorderGridLayout.verticalSpacing = 0; + pixelPerfectLoupeBorder.setLayout(pixelPerfectLoupeBorderGridLayout); + + mPixelPerfectLoupe = new PixelPerfectLoupe(pixelPerfectLoupeBorder); + mPixelPerfectLoupe.setLayoutData(new GridData(GridData.FILL_BOTH)); + + PixelPerfectPixelPanel pixelPerfectPixelPanel = new PixelPerfectPixelPanel(pixelPerfectLoupeBorder); + pixelPerfectPixelPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + PixelPerfectControls pixelPerfectControls = new PixelPerfectControls(parent); + pixelPerfectControls.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + placeActions(); + } + + private void placeActions() { + IActionBars actionBars = getViewSite().getActionBars(); + + IMenuManager mm = actionBars.getMenuManager(); + mm.removeAll(); + mm.add(PixelPerfectAutoRefreshAction.getAction()); + mm.add(mShowInLoupeAction); + + IToolBarManager tm = actionBars.getToolBarManager(); + tm.removeAll(); + tm.add(PixelPerfectAutoRefreshAction.getAction()); + tm.add(mShowInLoupeAction); + } + + @Override + public void dispose() { + super.dispose(); + PixelPerfectModel.getModel().removeImageChangeListener(this); + } + + @Override + public void setFocus() { + mPixelPerfectLoupe.setFocus(); + } + + @Override + public void crosshairMoved() { + // pass + } + + @Override + public void treeChanged() { + // pass + } + + @Override + public void imageChanged() { + // pass + } + + @Override + public void imageLoaded() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + Image overlayImage = PixelPerfectModel.getModel().getOverlayImage(); + mShowInLoupeAction.setEnabled(overlayImage != null); + } + }); + } + + @Override + public void overlayChanged() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + mShowInLoupeAction.setEnabled(PixelPerfectModel.getModel().getOverlayImage() != null); + } + }); + } + + @Override + public void overlayTransparencyChanged() { + // pass + } + + @Override + public void selectionChanged() { + // pass + } + + @Override + public void zoomChanged() { + // pass + } + +} diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/.classpath b/android-core/plugins/org.eclipse.andmore.integration.tests/.classpath index 6466c26e..30dcc906 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/.classpath +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/.classpath @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/.settings/org.eclipse.jdt.core.prefs b/android-core/plugins/org.eclipse.andmore.integration.tests/.settings/org.eclipse.jdt.core.prefs index ea661960..c137e176 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/.settings/org.eclipse.jdt.core.prefs +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,98 +1,98 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled +org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/META-INF/MANIFEST.MF b/android-core/plugins/org.eclipse.andmore.integration.tests/META-INF/MANIFEST.MF index fa9d4783..856c506c 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/META-INF/MANIFEST.MF +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/META-INF/MANIFEST.MF @@ -1,19 +1,15 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Android Plugin Tests -Bundle-SymbolicName: org.eclipse.andmore.integration.tests -Bundle-Version: 0.5.2.qualifier -Bundle-Vendor: Eclipse Andmore -Fragment-Host: org.eclipse.andmore -Require-Bundle: org.junit, - org.eclipse.andmore.base, - org.eclipse.andmore, - org.easymock, - org.custommonkey.xmlunit, - org.eclipse.andmore.android -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ClassPath: ., - libs/kxml2-2.3.0.jar, - libs/testutils.jar, - libs/lint-api.jar, - libs/lint-checks.jar +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Android Plugin Tests +Bundle-SymbolicName: org.eclipse.andmore.integration.tests +Bundle-Version: 0.5.2.qualifier +Bundle-Vendor: Eclipse Andmore +Fragment-Host: org.eclipse.andmore +Require-Bundle: org.junit, + org.eclipse.andmore.swt, + org.eclipse.andmore, + org.easymock, + org.custommonkey.xmlunit, + org.eclipse.andmore.android +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ClassPath: . diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/IntegrationTestSuite.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/IntegrationTestSuite.java index 87993eb1..f453efbc 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/IntegrationTestSuite.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/IntegrationTestSuite.java @@ -1,63 +1,64 @@ -/** - * Copyright (C) 2015 David Carver and others - * - * 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 org.eclipse.andmore.integration.tests; - -import org.eclipse.andmore.integration.tests.functests.sampleProjects.SampleProjectTest; -import org.eclipse.andmore.internal.build.AaptParserTest; -import org.eclipse.andmore.internal.build.AaptQuickFixTest; -import org.eclipse.andmore.internal.build.DexWrapperTest; -import org.eclipse.andmore.internal.editors.AndroidContentAssistTest; -import org.eclipse.andmore.internal.editors.AndroidXmlAutoEditStrategyTest; -import org.eclipse.andmore.internal.editors.AndroidXmlCharacterMatcherTest; -import org.eclipse.andmore.internal.editors.HyperlinksTest; -import org.eclipse.andmore.internal.editors.formatting.EclipseXmlPrettyPrinterTest; -import org.eclipse.andmore.internal.editors.layout.gle2.LayoutMetadataTest; -import org.eclipse.andmore.internal.editors.manifest.ManifestInfoTest; -import org.eclipse.andmore.internal.launch.JUnitLaunchConfigDelegateTest; -import org.eclipse.andmore.internal.lint.ProjectLintConfigurationTest; -import org.eclipse.andmore.internal.refactorings.core.AndroidPackageRenameParticipantTest; -import org.eclipse.andmore.internal.refactorings.core.RenameResourceParticipantTest; -import org.eclipse.andmore.internal.refactorings.renamepackage.ApplicationPackageNameRefactoringTest; -import org.eclipse.andmore.internal.settings.MultiDexTest; -import org.eclipse.andmore.internal.wizards.exportgradle.ExportGradleTest; -import org.eclipse.andmore.internal.wizards.templates.TemplateHandlerTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({SampleProjectTest.class, - AaptParserTest.class, - AaptQuickFixTest.class, - DexWrapperTest.class, - MultiDexTest.class, - EclipseXmlPrettyPrinterTest.class, - AndroidContentAssistTest.class, - AndroidXmlAutoEditStrategyTest.class, - AndroidXmlCharacterMatcherTest.class, - HyperlinksTest.class, - LayoutMetadataTest.class, - ManifestInfoTest.class, - JUnitLaunchConfigDelegateTest.class, - ProjectLintConfigurationTest.class, - AndroidPackageRenameParticipantTest.class, - RenameResourceParticipantTest.class, - ApplicationPackageNameRefactoringTest.class, - ExportGradleTest.class, - TemplateHandlerTest.class}) -public class IntegrationTestSuite { - -} +/** + * Copyright (C) 2015 David Carver and others + * + * 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 org.eclipse.andmore.integration.tests; + +import org.eclipse.andmore.integration.tests.functests.sampleProjects.SampleProjectTest; +import org.eclipse.andmore.internal.build.AaptParserTest; +import org.eclipse.andmore.internal.build.AaptQuickFixTest; +//import org.eclipse.andmore.internal.build.DexWrapperTest; +import org.eclipse.andmore.internal.editors.AndroidContentAssistTest; +import org.eclipse.andmore.internal.editors.AndroidXmlAutoEditStrategyTest; +import org.eclipse.andmore.internal.editors.AndroidXmlCharacterMatcherTest; +import org.eclipse.andmore.internal.editors.HyperlinksTest; +import org.eclipse.andmore.internal.editors.formatting.EclipseXmlPrettyPrinterTest; +import org.eclipse.andmore.internal.editors.layout.gle2.LayoutMetadataTest; +import org.eclipse.andmore.internal.editors.manifest.ManifestInfoTest; +import org.eclipse.andmore.internal.launch.JUnitLaunchConfigDelegateTest; +import org.eclipse.andmore.internal.lint.ProjectLintConfigurationTest; +import org.eclipse.andmore.internal.refactorings.core.AndroidPackageRenameParticipantTest; +import org.eclipse.andmore.internal.refactorings.core.RenameResourceParticipantTest; +import org.eclipse.andmore.internal.refactorings.renamepackage.ApplicationPackageNameRefactoringTest; +import org.eclipse.andmore.internal.settings.MultiDexTest; +import org.eclipse.andmore.internal.wizards.exportgradle.ExportGradleTest; +import org.eclipse.andmore.internal.wizards.templates.TemplateHandlerTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({SampleProjectTest.class, + AaptParserTest.class, + //AaptQuickFixTest.class, + // DexWrapper only works with build tools version 21 - 25 + //DexWrapperTest.class, + MultiDexTest.class, + EclipseXmlPrettyPrinterTest.class, + AndroidContentAssistTest.class, + AndroidXmlAutoEditStrategyTest.class, + AndroidXmlCharacterMatcherTest.class, + HyperlinksTest.class, + LayoutMetadataTest.class, + ManifestInfoTest.class, + JUnitLaunchConfigDelegateTest.class, + ProjectLintConfigurationTest.class, + AndroidPackageRenameParticipantTest.class, + RenameResourceParticipantTest.class, + ApplicationPackageNameRefactoringTest.class, + ExportGradleTest.class, + TemplateHandlerTest.class}) +public class IntegrationTestSuite { + +} diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkLoadingTestCase.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkLoadingTestCase.java index 10d88dad..89448ecd 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkLoadingTestCase.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkLoadingTestCase.java @@ -1,138 +1,138 @@ -/* - * 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 org.eclipse.andmore.integration.tests; - -import static org.junit.Assert.*; - -import java.io.File; - -import com.android.ide.common.sdk.LoadStatus; - -import org.eclipse.andmore.AndmoreAndroidPlugin; -import org.eclipse.andmore.AndmoreAndroidPlugin.CheckSdkErrorHandler; -import org.eclipse.andmore.internal.preferences.AdtPrefs; -import org.eclipse.andmore.internal.sdk.AndroidTargetParser; -import org.eclipse.andmore.internal.sdk.Sdk; - -import com.android.sdklib.IAndroidTarget; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.junit.After; -import org.junit.BeforeClass; - -/** - * A test case which uses the SDK loaded by the ADT plugin. - */ -public abstract class SdkLoadingTestCase extends SdkTestCase { - - private Sdk mSdk; - - - /** - * Retrieve the {@link Sdk} under test. - */ - protected Sdk getSdk() { - System.out.println("getSdk"); - if (mSdk == null) { - mSdk = loadSdk(); - assertNotNull(mSdk); - validateSdk(mSdk); - } - return mSdk; - } - - /** - * Gets the current SDK from ADT, waiting if necessary. - */ - private Sdk loadSdk() { - AndmoreAndroidPlugin adt = AndmoreAndroidPlugin.getDefault(); - - // We'll never get an AdtPlugin object when running this with the - // non-Eclipse jUnit test runner. - if (adt == null) { - return null; - } - - // We'll never break out of the SDK load-wait-loop if the AdtPlugin - // doesn't - // actually have a valid SDK location because it won't have started an - // async load: - //String sdkLocation = AdtPrefs.getPrefs().getOsSdkFolder(); - String sdkLocation = System.getenv("ANDROID_HOME"); - if (sdkLocation == null || sdkLocation.length() == 0) { - sdkLocation = System.getenv("ADT_TEST_SDK_PATH"); - } - assertTrue("No valid SDK installation is set; for tests you typically need to set the" - + " environment variable ADT_TEST_SDK_PATH to point to an SDK folder", sdkLocation != null - && sdkLocation.length() > 0); - AdtPrefs.getPrefs().setSdkLocation(new File(sdkLocation)); - - Object sdkLock = Sdk.getLock(); - LoadStatus loadStatus = LoadStatus.LOADING; - // wait for ADT to load the SDK on a separate thread - // loop max of 600 times * 200 ms = 2 minutes - final int maxWait = 600; - for (int i = 0; i < maxWait && loadStatus == LoadStatus.LOADING; i++) { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - // ignore - } - synchronized (sdkLock) { - loadStatus = adt.getSdkLoadStatus(); - } - } - Sdk sdk = null; - synchronized (sdkLock) { - assertEquals(LoadStatus.LOADED, loadStatus); - sdk = Sdk.getCurrent(); - } - - if (sdk.getTargets().length == 0) { - System.out.println("Did not find any valid targets. Reloading SDK from " + sdkLocation); - sdk = Sdk.loadSdk(sdkLocation); - } - assertNotNull(sdk); - return sdk; } - - protected boolean validateSdk(IAndroidTarget target) { - return true; - } - - /** - * Checks that the provided sdk contains one or more valid targets. - * - * @param sdk - * the {@link Sdk} to validate. - */ - @SuppressWarnings("unused") - private void validateSdk(Sdk sdk) { - assertTrue("sdk has no targets", sdk.getTargets().length > 0); - for (IAndroidTarget target : sdk.getTargets()) { - if (!validateSdk(target)) { - continue; - } - if (false) { // This takes forEVER - IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor()); - if (status.getCode() != IStatus.OK) { - fail("Failed to parse targets data"); - } - } - } - } -} +/* + * 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 org.eclipse.andmore.integration.tests; + +import static org.junit.Assert.*; + +import java.io.File; + +import com.android.ide.common.sdk.LoadStatus; + +import org.eclipse.andmore.AndmoreAndroidPlugin; +import org.eclipse.andmore.AndmoreAndroidPlugin.CheckSdkErrorHandler; +import org.eclipse.andmore.internal.preferences.AdtPrefs; +import org.eclipse.andmore.internal.sdk.AndroidTargetParser; +import org.eclipse.andmore.internal.sdk.Sdk; + +import com.android.sdklib.IAndroidTarget; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.junit.After; +import org.junit.BeforeClass; + +/** + * A test case which uses the SDK loaded by the ADT plugin. + */ +public abstract class SdkLoadingTestCase extends SdkTestCase { + + private Sdk mSdk; + + + /** + * Retrieve the {@link Sdk} under test. + */ + protected Sdk getSdk() { + System.out.println("getSdk"); + if (mSdk == null) { + mSdk = loadSdk(); + assertNotNull(mSdk); + validateSdk(mSdk); + } + return mSdk; + } + + /** + * Gets the current SDK from ADT, waiting if necessary. + */ + private Sdk loadSdk() { + AndmoreAndroidPlugin adt = AndmoreAndroidPlugin.getDefault(); + + // We'll never get an AdtPlugin object when running this with the + // non-Eclipse jUnit test runner. + if (adt == null) { + return null; + } + + // We'll never break out of the SDK load-wait-loop if the AdtPlugin + // doesn't + // actually have a valid SDK location because it won't have started an + // async load: + //String sdkLocation = AdtPrefs.getPrefs().getOsSdkFolder(); + String sdkLocation = System.getenv("ANDROID_HOME"); + if (sdkLocation == null || sdkLocation.length() == 0) { + sdkLocation = System.getenv("ADT_TEST_SDK_PATH"); + } + assertTrue("No valid SDK installation is set; for tests you typically need to set the" + + " environment variable ADT_TEST_SDK_PATH to point to an SDK folder", sdkLocation != null + && sdkLocation.length() > 0); + AdtPrefs.getPrefs().setSdkLocation(new File(sdkLocation)); + + Object sdkLock = Sdk.getLock(); + LoadStatus loadStatus = LoadStatus.LOADING; + // wait for ADT to load the SDK on a separate thread + // loop max of 600 times * 200 ms = 2 minutes + final int maxWait = 600; + for (int i = 0; i < maxWait && loadStatus == LoadStatus.LOADING; i++) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + // ignore + } + synchronized (sdkLock) { + loadStatus = adt.getSdkLoadStatus(); + } + } + Sdk sdk = null; + synchronized (sdkLock) { + assertEquals(LoadStatus.LOADED, loadStatus); + sdk = Sdk.getCurrent(); + } + + if (sdk.getTargets().size() == 0) { + System.out.println("Did not find any valid targets. Reloading SDK from " + sdkLocation); + sdk = Sdk.loadSdk(sdkLocation); + } + assertNotNull(sdk); + return sdk; } + + protected boolean validateSdk(IAndroidTarget target) { + return true; + } + + /** + * Checks that the provided sdk contains one or more valid targets. + * + * @param sdk + * the {@link Sdk} to validate. + */ + @SuppressWarnings("unused") + private void validateSdk(Sdk sdk) { + assertTrue("sdk has no targets", sdk.getTargets().size() > 0); + for (IAndroidTarget target : sdk.getTargets()) { + if (!validateSdk(target)) { + continue; + } + if (false) { // This takes forEVER + IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor()); + if (status.getCode() != IStatus.OK) { + fail("Failed to parse targets data"); + } + } + } + } +} diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkTestCase.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkTestCase.java index 808740ca..d74c7f66 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkTestCase.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/SdkTestCase.java @@ -1,423 +1,424 @@ -/* - * Copyright (C) 2012 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 org.eclipse.andmore.integration.tests; - -import static org.eclipse.andmore.test.utils.XMLAssert.*; - -import org.custommonkey.xmlunit.*; -import org.eclipse.andmore.AndmoreAndroidPlugin; - -import com.android.SdkConstants; -import com.google.common.base.Charsets; -import com.google.common.collect.Sets; -import com.google.common.io.ByteStreams; -import com.google.common.io.Closeables; -import com.google.common.io.Files; -import com.google.common.io.InputSupplier; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.rules.TemporaryFolder; -import org.junit.rules.TestName; -import org.xml.sax.SAXException; - -/** - * Common test case for SDK unit tests. Contains a number of general utility - * methods to help writing test cases, such as looking up a temporary directory, - * comparing golden files, computing string diffs, etc. - */ -@SuppressWarnings("javadoc") - - -public abstract class SdkTestCase { - - @Rule - public TestName testName = new TestName(); - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - - /** Update golden files if different from the actual results */ - private static final boolean UPDATE_DIFFERENT_FILES = false; - /** Create golden files if missing */ - private static final boolean UPDATE_MISSING_FILES = true; - protected static List sCleanDirs; - - protected String getTestDataRelPath() { - fail("Must be overridden"); - return null; - } - - @BeforeClass - public static void setupClass() { - sCleanDirs = new CopyOnWriteArrayList(); - } - - @AfterClass - public synchronized static void tearDown() { - for (File file : sCleanDirs) { - deleteFile(file); - - sCleanDirs.remove(file); - } - } - - @After - public void tearDownProjects() throws Exception { - System.out.println("Test Completed: " + testName.getMethodName()); - } - - public static int getCaretOffset(String fileContent, String caretLocation) { - assertTrue(caretLocation, caretLocation.contains("^")); //$NON-NLS-1$ - int caretDelta = caretLocation.indexOf("^"); //$NON-NLS-1$ - assertTrue(caretLocation, caretDelta != -1); - // String around caret/range without the range and caret marker - // characters - String caretContext; - if (caretLocation.contains("[^")) { //$NON-NLS-1$ - caretDelta--; - assertTrue(caretLocation, caretLocation.startsWith("[^", caretDelta)); //$NON-NLS-1$ - int caretRangeEnd = caretLocation.indexOf(']', caretDelta + 2); - assertTrue(caretLocation, caretRangeEnd != -1); - caretContext = caretLocation.substring(0, caretDelta) - + caretLocation.substring(caretDelta + 2, caretRangeEnd) - + caretLocation.substring(caretRangeEnd + 1); - } else { - caretContext = caretLocation.substring(0, caretDelta) + caretLocation.substring(caretDelta + 1); // +1: - // skip - // "^" - } - int caretContextIndex = fileContent.indexOf(caretContext); - assertTrue("Caret content " + caretContext + " not found in file", caretContextIndex != -1); - return caretContextIndex + caretDelta; - } - - public static String addSelection(String newFileContents, int selectionBegin, int selectionEnd) { - // Insert selection markers -- [ ] for the selection range, ^ for the - // caret - String newFileWithCaret; - if (selectionBegin < selectionEnd) { - newFileWithCaret = newFileContents.substring(0, selectionBegin) + "[^" - + newFileContents.substring(selectionBegin, selectionEnd) + "]" - + newFileContents.substring(selectionEnd); - } else { - // Selected range - newFileWithCaret = newFileContents.substring(0, selectionBegin) + "^" - + newFileContents.substring(selectionBegin); - } - return newFileWithCaret; - } - - public static String getCaretContext(String file, int offset) { - int windowSize = 20; - int begin = Math.max(0, offset - windowSize / 2); - int end = Math.min(file.length(), offset + windowSize / 2); - return "..." + file.substring(begin, offset) + "^" + file.substring(offset, end) + "..."; - } - - /** Get the location to write missing golden files to */ - protected File getTargetDir() { - // Set $ADT_SDK_SOURCE_PATH to point to your git "sdk" directory; if - // done, then - // if you run a unit test which refers to a golden file which does not - // exist, it - // will be created directly into the test data directory and you can - // rerun the - // test - // and it should pass (after you verify that the golden file contains - // the correct - // result of course). - String sdk = System.getenv("ADT_SDK_SOURCE_PATH"); - if (sdk != null) { - File sdkPath = new File(sdk); - if (sdkPath.exists()) { - File testData = new File(sdkPath, getTestDataRelPath().replace('/', File.separatorChar)); - if (testData.exists()) { - addCleanupDir(testData); - return testData; - } - } - } - return getTempDir(); - } - - public File getTempDir() { - return temporaryFolder.getRoot(); - } - - protected String removeSessionData(String data) { - return data; - } - - protected InputStream getTestResource(String relativePath, boolean expectExists) { - String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$ - InputStream stream = SdkTestCase.class.getResourceAsStream(path); - if (!expectExists && stream == null) { - return null; - } - return stream; - } - - @SuppressWarnings("resource") - protected String readTestFile(String relativePath, boolean expectExists) throws IOException { - InputStream stream = getTestResource(relativePath, expectExists); - if (expectExists) { - assertNotNull(relativePath + " does not exist", stream); - } else if (stream == null) { - return null; - } - String xml = new String(ByteStreams.toByteArray(stream), Charsets.UTF_8); - try { - Closeables.close(stream, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - assertTrue(xml.length() > 0); - // Remove any references to the project name such that we are isolated - // from - // that in golden file. - // Appears in strings.xml etc. - xml = removeSessionData(xml); - return xml; - } - - protected void assertEqualsGolden(String basename, String actual) throws IOException { - assertEqualsGolden(basename, actual, basename.substring(basename.lastIndexOf('.') + 1)); - } - - protected void assertEqualsGolden(String basename, String actual, String newExtension) throws IOException { - String testName = this.testName.getMethodName(); - if (testName.startsWith("test")) { - testName = testName.substring(4); - if (Character.isUpperCase(testName.charAt(0))) { - testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1); - } - } - String expectedName; - String extension = basename.substring(basename.lastIndexOf('.') + 1); - if (newExtension == null) { - newExtension = extension; - } - expectedName = basename.substring(0, basename.indexOf('.')) + "-expected-" + testName + '.' + newExtension; - String expected = readTestFile(expectedName, false); - if (expected == null) { - File expectedPath = new File(UPDATE_MISSING_FILES ? getTargetDir() : getTempDir(), expectedName); - Files.write(actual, expectedPath, Charsets.UTF_8); - System.out.println("Expected - written to " + expectedPath + ":\n"); - System.out.println(actual); - fail("Did not find golden file (" + expectedName + "): Wrote contents as " + expectedPath); - } else { - if (!expected.replaceAll("\r\n", "\n").equals(actual.replaceAll("\r\n", "\n"))) { - File expectedPath = new File(getTempDir(), expectedName); - File actualPath = new File(getTempDir(), expectedName.replace("expected", "actual")); - Files.write(expected, expectedPath, Charsets.UTF_8); - Files.write(actual, actualPath, Charsets.UTF_8); - // Also update data dir with the current value - if (UPDATE_DIFFERENT_FILES) { - Files.write(actual, new File(getTargetDir(), expectedName), Charsets.UTF_8); - } - System.out.println("The files differ: diff " + expectedPath + " " + actualPath); - Reader expectedReader = new InputStreamReader( new FileInputStream(expectedPath)); - Reader actualReader = new InputStreamReader(new FileInputStream(actualPath)); - - try { - XMLUnit.setIgnoreAttributeOrder(true); - XMLUnit.setIgnoreWhitespace(true); - assertXMLEqual(expectedReader, actualReader); - } catch (SAXException e) { - assertEquals("The files differ - see " + expectedPath + " versus " + actualPath, expected, actual); - } finally { - expectedReader.close(); - actualReader.close(); - } - } - } - } - - /** Creates a diff of two strings */ - public static String getDiff(String before, String after) { - return getDiff(before.split("\n"), after.split("\n")); - } - - public static String getDiff(String[] before, String[] after) { - // Based on the LCS section in - // http://introcs.cs.princeton.edu/java/96optimization/ - StringBuilder sb = new StringBuilder(); - int n = before.length; - int m = after.length; - // Compute longest common subsequence of x[i..m] and y[j..n] bottom up - int[][] lcs = new int[n + 1][m + 1]; - for (int i = n - 1; i >= 0; i--) { - for (int j = m - 1; j >= 0; j--) { - if (before[i].equals(after[j])) { - lcs[i][j] = lcs[i + 1][j + 1] + 1; - } else { - lcs[i][j] = Math.max(lcs[i + 1][j], lcs[i][j + 1]); - } - } - } - int i = 0; - int j = 0; - while ((i < n) && (j < m)) { - if (before[i].equals(after[j])) { - i++; - j++; - } else { - sb.append("@@ -"); - sb.append(Integer.toString(i + 1)); - sb.append(" +"); - sb.append(Integer.toString(j + 1)); - sb.append('\n'); - while (i < n && j < m && !before[i].equals(after[j])) { - if (lcs[i + 1][j] >= lcs[i][j + 1]) { - sb.append('-'); - if (!before[i].trim().isEmpty()) { - sb.append(' '); - } - sb.append(before[i]); - sb.append('\n'); - i++; - } else { - sb.append('+'); - if (!after[j].trim().isEmpty()) { - sb.append(' '); - } - sb.append(after[j]); - sb.append('\n'); - j++; - } - } - } - } - if (i < n || j < m) { - assert i == n || j == m; - sb.append("@@ -"); - sb.append(Integer.toString(i + 1)); - sb.append(" +"); - sb.append(Integer.toString(j + 1)); - sb.append('\n'); - for (; i < n; i++) { - sb.append('-'); - if (!before[i].trim().isEmpty()) { - sb.append(' '); - } - sb.append(before[i]); - sb.append('\n'); - } - for (; j < m; j++) { - sb.append('+'); - if (!after[j].trim().isEmpty()) { - sb.append(' '); - } - sb.append(after[j]); - sb.append('\n'); - } - } - return sb.toString(); - } - - public static void deleteFile(File dir) { - if (dir.isDirectory()) { - for (File f : dir.listFiles()) { - deleteFile(f); - } - } else if (dir.isFile()) { - assertTrue(dir.getPath(), dir.delete()); - } - } - - protected File makeTestFile(String name, String relative, final InputStream contents) throws IOException { - return makeTestFile(getTargetDir(), name, relative, contents); - } - - protected File makeTestFile(File dir, String name, String relative, final InputStream contents) throws IOException { - if (relative != null) { - dir = new File(dir, relative); - if (!dir.exists()) { - boolean mkdir = dir.mkdirs(); - assertTrue(dir.getPath(), mkdir); - } - } else if (!dir.exists()) { - boolean mkdir = dir.mkdirs(); - assertTrue(dir.getPath(), mkdir); - } - File tempFile = new File(dir, name); - if (tempFile.exists()) { - tempFile.delete(); - } - Files.copy(new InputSupplier() { - @Override - public InputStream getInput() throws IOException { - return contents; - } - }, tempFile); - return tempFile; - } - - protected File getTestfile(File targetDir, String relativePath) throws IOException { - // Support replacing filenames and paths with a => syntax, e.g. - // dir/file.txt=>dir2/dir3/file2.java - // will read dir/file.txt from the test data and write it into the - // target - // directory as dir2/dir3/file2.java - String targetPath = relativePath; - int replaceIndex = relativePath.indexOf("=>"); //$NON-NLS-1$ - if (replaceIndex != -1) { - // foo=>bar - targetPath = relativePath.substring(replaceIndex + "=>".length()); - relativePath = relativePath.substring(0, replaceIndex); - } - InputStream stream = getTestResource(relativePath, true); - assertNotNull(relativePath + " does not exist", stream); - int index = targetPath.lastIndexOf('/'); - String relative = null; - String name = targetPath; - if (index != -1) { - name = targetPath.substring(index + 1); - relative = targetPath.substring(0, index); - } - return makeTestFile(targetDir, name, relative, stream); - } - - protected static void addCleanupDir(File dir) { - sCleanDirs.add(dir); - try { - sCleanDirs.add(dir.getCanonicalFile()); - } catch (IOException e) { - fail(e.getLocalizedMessage()); - } - sCleanDirs.add(dir.getAbsoluteFile()); - } - - +/* + * Copyright (C) 2012 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 org.eclipse.andmore.integration.tests; + +import static org.eclipse.andmore.test.utils.XMLAssert.*; + +import org.custommonkey.xmlunit.*; +import org.eclipse.andmore.AndmoreAndroidPlugin; + +import com.android.SdkConstants; +import com.google.common.base.Charsets; +import com.google.common.collect.Sets; +import com.google.common.io.ByteStreams; +import com.google.common.io.Closeables; +import com.google.common.io.Files; +import com.google.common.io.ByteSource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestName; +import org.xml.sax.SAXException; + +/** + * Common test case for SDK unit tests. Contains a number of general utility + * methods to help writing test cases, such as looking up a temporary directory, + * comparing golden files, computing string diffs, etc. + */ +@SuppressWarnings("javadoc") + + +public abstract class SdkTestCase { + + @Rule + public TestName testName = new TestName(); + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + + /** Update golden files if different from the actual results */ + private static final boolean UPDATE_DIFFERENT_FILES = false; + /** Create golden files if missing */ + private static final boolean UPDATE_MISSING_FILES = true; + protected static List sCleanDirs; + + protected String getTestDataRelPath() { + fail("Must be overridden"); + return null; + } + + @BeforeClass + public static void setupClass() { + sCleanDirs = new CopyOnWriteArrayList(); + } + + @AfterClass + public synchronized static void tearDown() { + for (File file : sCleanDirs) { + deleteFile(file); + + sCleanDirs.remove(file); + } + } + + @After + public void tearDownProjects() throws Exception { + System.out.println("Test Completed: " + testName.getMethodName()); + } + + public static int getCaretOffset(String fileContent, String caretLocation) { + assertTrue(caretLocation, caretLocation.contains("^")); //$NON-NLS-1$ + int caretDelta = caretLocation.indexOf("^"); //$NON-NLS-1$ + assertTrue(caretLocation, caretDelta != -1); + // String around caret/range without the range and caret marker + // characters + String caretContext; + if (caretLocation.contains("[^")) { //$NON-NLS-1$ + caretDelta--; + assertTrue(caretLocation, caretLocation.startsWith("[^", caretDelta)); //$NON-NLS-1$ + int caretRangeEnd = caretLocation.indexOf(']', caretDelta + 2); + assertTrue(caretLocation, caretRangeEnd != -1); + caretContext = caretLocation.substring(0, caretDelta) + + caretLocation.substring(caretDelta + 2, caretRangeEnd) + + caretLocation.substring(caretRangeEnd + 1); + } else { + caretContext = caretLocation.substring(0, caretDelta) + caretLocation.substring(caretDelta + 1); // +1: + // skip + // "^" + } + int caretContextIndex = fileContent.indexOf(caretContext); + assertTrue("Caret content " + caretContext + " not found in file", caretContextIndex != -1); + return caretContextIndex + caretDelta; + } + + public static String addSelection(String newFileContents, int selectionBegin, int selectionEnd) { + // Insert selection markers -- [ ] for the selection range, ^ for the + // caret + String newFileWithCaret; + if (selectionBegin < selectionEnd) { + newFileWithCaret = newFileContents.substring(0, selectionBegin) + "[^" + + newFileContents.substring(selectionBegin, selectionEnd) + "]" + + newFileContents.substring(selectionEnd); + } else { + // Selected range + newFileWithCaret = newFileContents.substring(0, selectionBegin) + "^" + + newFileContents.substring(selectionBegin); + } + return newFileWithCaret; + } + + public static String getCaretContext(String file, int offset) { + int windowSize = 20; + int begin = Math.max(0, offset - windowSize / 2); + int end = Math.min(file.length(), offset + windowSize / 2); + return "..." + file.substring(begin, offset) + "^" + file.substring(offset, end) + "..."; + } + + /** Get the location to write missing golden files to */ + protected File getTargetDir() { + // Set $ADT_SDK_SOURCE_PATH to point to your git "sdk" directory; if + // done, then + // if you run a unit test which refers to a golden file which does not + // exist, it + // will be created directly into the test data directory and you can + // rerun the + // test + // and it should pass (after you verify that the golden file contains + // the correct + // result of course). + String sdk = System.getenv("ADT_SDK_SOURCE_PATH"); + if (sdk != null) { + File sdkPath = new File(sdk); + if (sdkPath.exists()) { + File testData = new File(sdkPath, getTestDataRelPath().replace('/', File.separatorChar)); + if (testData.exists()) { + addCleanupDir(testData); + return testData; + } + } + } + return getTempDir(); + } + + public File getTempDir() { + return temporaryFolder.getRoot(); + } + + protected String removeSessionData(String data) { + return data; + } + + protected InputStream getTestResource(String relativePath, boolean expectExists) { + String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$ + InputStream stream = SdkTestCase.class.getResourceAsStream(path); + if (!expectExists && stream == null) { + return null; + } + return stream; + } + + @SuppressWarnings("resource") + protected String readTestFile(String relativePath, boolean expectExists) throws IOException { + InputStream stream = getTestResource(relativePath, expectExists); + if (expectExists) { + assertNotNull(relativePath + " does not exist", stream); + } else if (stream == null) { + return null; + } + String xml = new String(ByteStreams.toByteArray(stream), Charsets.UTF_8); + try { + Closeables.close(stream, true /* swallowIOException */); + } catch (IOException e) { + // cannot happen + } + assertTrue(xml.length() > 0); + // Remove any references to the project name such that we are isolated + // from + // that in golden file. + // Appears in strings.xml etc. + xml = removeSessionData(xml); + return xml; + } + + protected void assertEqualsGolden(String basename, String actual) throws IOException { + assertEqualsGolden(basename, actual, basename.substring(basename.lastIndexOf('.') + 1)); + } + + protected void assertEqualsGolden(String basename, String actual, String newExtension) throws IOException { + String testName = this.testName.getMethodName(); + if (testName.startsWith("test")) { + testName = testName.substring(4); + if (Character.isUpperCase(testName.charAt(0))) { + testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1); + } + } + String expectedName; + String extension = basename.substring(basename.lastIndexOf('.') + 1); + if (newExtension == null) { + newExtension = extension; + } + expectedName = basename.substring(0, basename.indexOf('.')) + "-expected-" + testName + '.' + newExtension; + String expected = readTestFile(expectedName, false); + if (expected == null) { + File expectedPath = new File(UPDATE_MISSING_FILES ? getTargetDir() : getTempDir(), expectedName); + Files.write(actual, expectedPath, Charsets.UTF_8); + System.out.println("Expected - written to " + expectedPath + ":\n"); + System.out.println(actual); + fail("Did not find golden file (" + expectedName + "): Wrote contents as " + expectedPath); + } else { + if (!expected.replaceAll("\r\n", "\n").equals(actual.replaceAll("\r\n", "\n"))) { + File expectedPath = new File(getTempDir(), expectedName); + File actualPath = new File(getTempDir(), expectedName.replace("expected", "actual")); + Files.write(expected, expectedPath, Charsets.UTF_8); + Files.write(actual, actualPath, Charsets.UTF_8); + // Also update data dir with the current value + if (UPDATE_DIFFERENT_FILES) { + Files.write(actual, new File(getTargetDir(), expectedName), Charsets.UTF_8); + } + System.out.println("The files differ: diff " + expectedPath + " " + actualPath); + Reader expectedReader = new InputStreamReader( new FileInputStream(expectedPath)); + Reader actualReader = new InputStreamReader(new FileInputStream(actualPath)); + + try { + XMLUnit.setIgnoreAttributeOrder(true); + XMLUnit.setIgnoreWhitespace(true); + assertXMLEqual(expectedReader, actualReader); + } catch (SAXException e) { + assertEquals("The files differ - see " + expectedPath + " versus " + actualPath, expected, actual); + } finally { + expectedReader.close(); + actualReader.close(); + } + } + } + } + + /** Creates a diff of two strings */ + public static String getDiff(String before, String after) { + return getDiff(before.split("\n"), after.split("\n")); + } + + public static String getDiff(String[] before, String[] after) { + // Based on the LCS section in + // http://introcs.cs.princeton.edu/java/96optimization/ + StringBuilder sb = new StringBuilder(); + int n = before.length; + int m = after.length; + // Compute longest common subsequence of x[i..m] and y[j..n] bottom up + int[][] lcs = new int[n + 1][m + 1]; + for (int i = n - 1; i >= 0; i--) { + for (int j = m - 1; j >= 0; j--) { + if (before[i].equals(after[j])) { + lcs[i][j] = lcs[i + 1][j + 1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i + 1][j], lcs[i][j + 1]); + } + } + } + int i = 0; + int j = 0; + while ((i < n) && (j < m)) { + if (before[i].equals(after[j])) { + i++; + j++; + } else { + sb.append("@@ -"); + sb.append(Integer.toString(i + 1)); + sb.append(" +"); + sb.append(Integer.toString(j + 1)); + sb.append('\n'); + while (i < n && j < m && !before[i].equals(after[j])) { + if (lcs[i + 1][j] >= lcs[i][j + 1]) { + sb.append('-'); + if (!before[i].trim().isEmpty()) { + sb.append(' '); + } + sb.append(before[i]); + sb.append('\n'); + i++; + } else { + sb.append('+'); + if (!after[j].trim().isEmpty()) { + sb.append(' '); + } + sb.append(after[j]); + sb.append('\n'); + j++; + } + } + } + } + if (i < n || j < m) { + assert i == n || j == m; + sb.append("@@ -"); + sb.append(Integer.toString(i + 1)); + sb.append(" +"); + sb.append(Integer.toString(j + 1)); + sb.append('\n'); + for (; i < n; i++) { + sb.append('-'); + if (!before[i].trim().isEmpty()) { + sb.append(' '); + } + sb.append(before[i]); + sb.append('\n'); + } + for (; j < m; j++) { + sb.append('+'); + if (!after[j].trim().isEmpty()) { + sb.append(' '); + } + sb.append(after[j]); + sb.append('\n'); + } + } + return sb.toString(); + } + + public static void deleteFile(File dir) { + if (dir.isDirectory()) { + for (File f : dir.listFiles()) { + deleteFile(f); + } + } else if (dir.isFile()) { + assertTrue(dir.getPath(), dir.delete()); + } + } + + protected File makeTestFile(String name, String relative, final InputStream contents) throws IOException { + return makeTestFile(getTargetDir(), name, relative, contents); + } + + protected File makeTestFile(File dir, String name, String relative, final InputStream contents) throws IOException { + if (relative != null) { + dir = new File(dir, relative); + if (!dir.exists()) { + boolean mkdir = dir.mkdirs(); + assertTrue(dir.getPath(), mkdir); + } + } else if (!dir.exists()) { + boolean mkdir = dir.mkdirs(); + assertTrue(dir.getPath(), mkdir); + } + File tempFile = new File(dir, name); + if (tempFile.exists()) { + tempFile.delete(); + } + ByteSource byteSource = new ByteSource() { + @Override + public InputStream openStream() throws IOException { + return contents; + } + }; + byteSource.copyTo(Files.asByteSink(tempFile)); + return tempFile; + } + + protected File getTestfile(File targetDir, String relativePath) throws IOException { + // Support replacing filenames and paths with a => syntax, e.g. + // dir/file.txt=>dir2/dir3/file2.java + // will read dir/file.txt from the test data and write it into the + // target + // directory as dir2/dir3/file2.java + String targetPath = relativePath; + int replaceIndex = relativePath.indexOf("=>"); //$NON-NLS-1$ + if (replaceIndex != -1) { + // foo=>bar + targetPath = relativePath.substring(replaceIndex + "=>".length()); + relativePath = relativePath.substring(0, replaceIndex); + } + InputStream stream = getTestResource(relativePath, true); + assertNotNull(relativePath + " does not exist", stream); + int index = targetPath.lastIndexOf('/'); + String relative = null; + String name = targetPath; + if (index != -1) { + name = targetPath.substring(index + 1); + relative = targetPath.substring(0, index); + } + return makeTestFile(targetDir, name, relative, stream); + } + + protected static void addCleanupDir(File dir) { + sCleanDirs.add(dir); + try { + sCleanDirs.add(dir.getCanonicalFile()); + } catch (IOException e) { + fail(e.getLocalizedMessage()); + } + sCleanDirs.add(dir.getAbsoluteFile()); + } + + } \ No newline at end of file diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/layoutRendering/ApiDemosRenderingTest.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/layoutRendering/ApiDemosRenderingTest.java index c08d8387..9a55f069 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/layoutRendering/ApiDemosRenderingTest.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/layoutRendering/ApiDemosRenderingTest.java @@ -1,333 +1,332 @@ -/* - * Copyright (C) 2009 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 org.eclipse.andmore.integration.tests.functests.layoutRendering; - -import static org.junit.Assert.*; - -import com.android.SdkConstants; -import com.android.ide.common.rendering.LayoutLibrary; -import com.android.ide.common.rendering.api.ActionBarCallback; -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.LayoutlibCallback; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.resources.ResourceItem; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.common.resources.ResourceResolver; -import com.android.ide.common.resources.configuration.DensityQualifier; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.ide.common.resources.configuration.KeyboardStateQualifier; -import com.android.ide.common.resources.configuration.NavigationMethodQualifier; -import com.android.ide.common.resources.configuration.NavigationStateQualifier; -import com.android.ide.common.resources.configuration.ScreenDimensionQualifier; -import com.android.ide.common.resources.configuration.ScreenHeightQualifier; -import com.android.ide.common.resources.configuration.ScreenOrientationQualifier; -import com.android.ide.common.resources.configuration.ScreenRatioQualifier; -import com.android.ide.common.resources.configuration.ScreenSizeQualifier; -import com.android.ide.common.resources.configuration.ScreenWidthQualifier; -import com.android.ide.common.resources.configuration.SmallestScreenWidthQualifier; -import com.android.ide.common.resources.configuration.TextInputMethodQualifier; -import com.android.ide.common.resources.configuration.TouchScreenQualifier; -import com.android.ide.common.sdk.LoadStatus; - -import org.eclipse.andmore.integration.tests.SdkLoadingTestCase; -import org.eclipse.andmore.internal.resources.manager.ResourceManager; -import org.eclipse.andmore.internal.sdk.AndroidTargetData; - -import com.android.io.FolderWrapper; -import com.android.resources.Density; -import com.android.resources.Keyboard; -import com.android.resources.KeyboardState; -import com.android.resources.Navigation; -import com.android.resources.NavigationState; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.resources.ScreenRatio; -import com.android.resources.ScreenRound; -import com.android.resources.ScreenSize; -import com.android.resources.TouchScreen; -import com.android.sdklib.IAndroidTarget; -import com.android.util.Pair; - -import org.junit.Ignore; -import org.junit.Test; -import org.kxml2.io.KXmlParser; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.imageio.ImageIO; - -@Ignore -public class ApiDemosRenderingTest extends SdkLoadingTestCase { - - /** - * Custom parser that implements {@link ILayoutPullParser} (which itself - * extends {@link XmlPullParser}). - */ - private final static class TestParser extends KXmlParser implements ILayoutPullParser { - /** - * Since we're not going to go through the result of the - * rendering/layout, we can return null for the View Key. - */ - @Override - public Object getViewCookie() { - return null; - } - - @Override - public ILayoutPullParser getParser(String layoutName) { - return null; - } - } - - private final static class ProjectCallBack extends LayoutlibCallback { - // resource id counter. - // We start at 0x7f000000 to avoid colliding with the framework id - // since we have no access to the project R.java and we need to generate - // them automatically. - private int mIdCounter = 0x7f000000; - - // in some cases, the id that getResourceValue(String type, String name) - // returns - // will be sent back to get the type/name. This map stores the - // id/type/name we generate - // to be able to do the reverse resolution. - private Map> mResourceMap = new HashMap>(); - - private boolean mCustomViewAttempt = false; - - @Override - public String getNamespace() { - // TODO: read from the ApiDemos manifest. - return "com.example.android.apis"; - } - - @Override - @SuppressWarnings("unchecked") - public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs) - throws ClassNotFoundException, Exception { - mCustomViewAttempt = true; - return null; - } - - @Override - public Integer getResourceId(ResourceType type, String name) { - Integer result = ++mIdCounter; - mResourceMap.put(result, Pair.of(type, name)); - return result; - } - - @Override - public Pair resolveResourceId(int id) { - return mResourceMap.get(id); - } - - @Override - public String resolveResourceId(int[] id) { - return null; - } - - @Override - public ILayoutPullParser getParser(String layoutName) { - return null; - } - - @Override - public Object getAdapterItemValue(ResourceReference adapterView, Object adapterCookie, - ResourceReference itemRef, int fullPosition, int typePosition, int fullChildPosition, - int typeChildPosition, ResourceReference viewRef, ViewAttribute viewAttribute, Object defaultValue) { - return null; - } - - @Override - public AdapterBinding getAdapterBinding(ResourceReference adapterView, Object adapterCookie, Object viewObject) { - return null; - } - - @Override - public ILayoutPullParser getParser(ResourceValue layoutResource) { - return null; - } - - @Override - public ActionBarCallback getActionBarCallback() { - return new ActionBarCallback(); - } - - @Override - public boolean supports(int ideFeature) { - // TODO Auto-generated method stub - return false; - } - } - - @Test - public void testApiDemos() throws IOException, XmlPullParserException { - findApiDemos(); - } - - private void findApiDemos() throws IOException, XmlPullParserException { - IAndroidTarget[] targets = getSdk().getTargets(); - - for (IAndroidTarget target : targets) { - String path = target.getPath(IAndroidTarget.SAMPLES); - File samples = new File(path); - if (samples.isDirectory()) { - File[] files = samples.listFiles(); - for (File file : files) { - if ("apidemos".equalsIgnoreCase(file.getName())) { - testSample(target, file); - return; - } - } - } - } - - fail("Failed to find ApiDemos!"); - } - - private void testSample(IAndroidTarget target, File sampleProject) throws IOException, XmlPullParserException { - AndroidTargetData data = getSdk().getTargetData(target); - if (data == null) { - fail("No AndroidData!"); - } - - LayoutLibrary layoutLib = data.getLayoutLibrary(); - if (layoutLib.getStatus() != LoadStatus.LOADED) { - fail("Fail to load the bridge: " + layoutLib.getLoadMessage()); - } - - FolderWrapper resFolder = new FolderWrapper(sampleProject, SdkConstants.FD_RES); - if (resFolder.exists() == false) { - fail("Sample project has no res folder!"); - } - - // look for the layout folder - File layoutFolder = new File(resFolder, SdkConstants.FD_RES_LAYOUT); - if (layoutFolder.isDirectory() == false) { - fail("Sample project has no layout folder!"); - } - - // first load the project's target framework resource - ResourceRepository framework = ResourceManager.getInstance().loadFrameworkResources(target); - - // now load the project resources - ResourceRepository project = new ResourceRepository(resFolder, false) { - @Override - protected ResourceItem createResourceItem(String name) { - return new ResourceItem(name); - } - - }; - - // Create a folder configuration that will be used for the rendering: - FolderConfiguration config = getConfiguration(); - - // get the configured resources - Map> configuredFramework = framework.getConfiguredResources(config); - Map> configuredProject = project.getConfiguredResources(config); - - boolean saveFiles = System.getenv("save_file") != null; - - // loop on the layouts and render them - File[] layouts = layoutFolder.listFiles(); - for (File layout : layouts) { - // create a parser for the layout file - TestParser parser = new TestParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileReader(layout)); - - System.out.println("Rendering " + layout.getName()); - - ProjectCallBack projectCallBack = new ProjectCallBack(); - - ResourceResolver resolver = ResourceResolver - .create(configuredProject, configuredFramework, "Theme", false /* isProjectTheme */); - - HardwareConfig hardwareConfig = new HardwareConfig(320, 480, Density.MEDIUM, 160, // xdpi - 160, // ydpi - ScreenSize.NORMAL, ScreenOrientation.PORTRAIT, ScreenRound.NOTROUND, false /* - * software - * buttons - */); - - RenderSession session = layoutLib.createSession(new SessionParams(parser, RenderingMode.NORMAL, - null /* projectKey */, hardwareConfig, resolver, projectCallBack, 1, // minSdkVersion - 1, // targetSdkVersion - null // logger - )); - - if (session.getResult().isSuccess() == false) { - if (projectCallBack.mCustomViewAttempt == false) { - System.out.println("FAILED"); - fail(String.format("Rendering %1$s: %2$s", layout.getName(), session.getResult().getErrorMessage())); - } else { - System.out.println("Ignore custom views for now"); - } - } else { - if (saveFiles) { - File tmp = File.createTempFile(layout.getName(), ".png"); - ImageIO.write(session.getImage(), "png", tmp); - } - System.out.println("Success!"); - } - } - } - - /** - * Returns a config. This must be a valid config like a device would return. - * This is to prevent issues where some resources don't exist in all cases - * and not in the default (for instance only available in hdpi and mdpi but - * not in default). - * - * @return - */ - private FolderConfiguration getConfiguration() { - FolderConfiguration config = new FolderConfiguration(); - - // this matches an ADP1. - config.addQualifier(new SmallestScreenWidthQualifier(320)); - config.addQualifier(new ScreenWidthQualifier(320)); - config.addQualifier(new ScreenHeightQualifier(480)); - config.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL)); - config.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG)); - config.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT)); - config.addQualifier(new DensityQualifier(Density.MEDIUM)); - config.addQualifier(new TouchScreenQualifier(TouchScreen.FINGER)); - config.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN)); - config.addQualifier(new TextInputMethodQualifier(Keyboard.QWERTY)); - config.addQualifier(new NavigationStateQualifier(NavigationState.HIDDEN)); - config.addQualifier(new NavigationMethodQualifier(Navigation.TRACKBALL)); - config.addQualifier(new ScreenDimensionQualifier(480, 320)); - - config.updateScreenWidthAndHeight(); - - return config; - } -} +/* + * Copyright (C) 2009 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 org.eclipse.andmore.integration.tests.functests.layoutRendering; + +import static org.junit.Assert.*; + +import com.android.SdkConstants; +import com.android.ide.common.rendering.LayoutLibrary; +import com.android.ide.common.rendering.api.ActionBarCallback; +import com.android.ide.common.rendering.api.AdapterBinding; +import com.android.ide.common.rendering.api.HardwareConfig; +import com.android.ide.common.rendering.api.ILayoutPullParser; +import com.android.ide.common.rendering.api.IProjectCallback; +import com.android.ide.common.rendering.api.LayoutlibCallback; +import com.android.ide.common.rendering.api.RenderSession; +import com.android.ide.common.rendering.api.ResourceReference; +import com.android.ide.common.rendering.api.ResourceValue; +import com.android.ide.common.resources.ResourceValueMap; +import com.android.ide.common.rendering.api.SessionParams; +import com.android.ide.common.rendering.api.SessionParams.RenderingMode; +import com.android.ide.common.resources.ResourceItem; +import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceResolver; +import com.android.ide.common.resources.configuration.DensityQualifier; +import com.android.ide.common.resources.configuration.FolderConfiguration; +import com.android.ide.common.resources.configuration.KeyboardStateQualifier; +import com.android.ide.common.resources.configuration.NavigationMethodQualifier; +import com.android.ide.common.resources.configuration.NavigationStateQualifier; +import com.android.ide.common.resources.configuration.ScreenDimensionQualifier; +import com.android.ide.common.resources.configuration.ScreenHeightQualifier; +import com.android.ide.common.resources.configuration.ScreenOrientationQualifier; +import com.android.ide.common.resources.configuration.ScreenRatioQualifier; +import com.android.ide.common.resources.configuration.ScreenSizeQualifier; +import com.android.ide.common.resources.configuration.ScreenWidthQualifier; +import com.android.ide.common.resources.configuration.SmallestScreenWidthQualifier; +import com.android.ide.common.resources.configuration.TextInputMethodQualifier; +import com.android.ide.common.resources.configuration.TouchScreenQualifier; +import com.android.ide.common.sdk.LoadStatus; + +import org.eclipse.andmore.integration.tests.SdkLoadingTestCase; +import org.eclipse.andmore.internal.resources.manager.ResourceManager; +import org.eclipse.andmore.internal.sdk.AndroidTargetData; + +import com.android.io.FolderWrapper; +import com.android.resources.Density; +import com.android.resources.Keyboard; +import com.android.resources.KeyboardState; +import com.android.resources.Navigation; +import com.android.resources.NavigationState; +import com.android.resources.ResourceType; +import com.android.resources.ScreenOrientation; +import com.android.resources.ScreenRatio; +import com.android.resources.ScreenRound; +import com.android.resources.ScreenSize; +import com.android.resources.TouchScreen; +import com.android.sdklib.IAndroidTarget; +import com.android.util.Pair; + +import org.junit.Ignore; +import org.junit.Test; +import org.kxml2.io.KXmlParser; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.ImageIO; + +@Ignore +public class ApiDemosRenderingTest extends SdkLoadingTestCase { + + /** + * Custom parser that implements {@link ILayoutPullParser} (which itself + * extends {@link XmlPullParser}). + */ + private final static class TestParser extends KXmlParser implements ILayoutPullParser { + /** + * Since we're not going to go through the result of the + * rendering/layout, we can return null for the View Key. + */ + @Override + public Object getViewCookie() { + return null; + } + + @Override + public ILayoutPullParser getParser(String layoutName) { + return null; + } + } + + private final static class ProjectCallBack extends LayoutlibCallback { + // resource id counter. + // We start at 0x7f000000 to avoid colliding with the framework id + // since we have no access to the project R.java and we need to generate + // them automatically. + private int mIdCounter = 0x7f000000; + + // in some cases, the id that getResourceValue(String type, String name) + // returns + // will be sent back to get the type/name. This map stores the + // id/type/name we generate + // to be able to do the reverse resolution. + private Map> mResourceMap = new HashMap>(); + + private boolean mCustomViewAttempt = false; + + @Override + public String getNamespace() { + // TODO: read from the ApiDemos manifest. + return "com.example.android.apis"; + } + + @Override + @SuppressWarnings("unchecked") + public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs) + throws ClassNotFoundException, Exception { + mCustomViewAttempt = true; + return null; + } + + @Override + public Integer getResourceId(ResourceType type, String name) { + Integer result = ++mIdCounter; + mResourceMap.put(result, Pair.of(type, name)); + return result; + } + + @Override + public Pair resolveResourceId(int id) { + return mResourceMap.get(id); + } + + @Override + public String resolveResourceId(int[] id) { + return null; + } + + @Override + public ILayoutPullParser getParser(String layoutName) { + return null; + } + + @Override + public Object getAdapterItemValue(ResourceReference adapterView, Object adapterCookie, + ResourceReference itemRef, int fullPosition, int typePosition, int fullChildPosition, + int typeChildPosition, ResourceReference viewRef, ViewAttribute viewAttribute, Object defaultValue) { + return null; + } + + @Override + public AdapterBinding getAdapterBinding(ResourceReference adapterView, Object adapterCookie, Object viewObject) { + return null; + } + + @Override + public ILayoutPullParser getParser(ResourceValue layoutResource) { + return null; + } + + @Override + public ActionBarCallback getActionBarCallback() { + return new ActionBarCallback(); + } + + @Override + public boolean supports(int ideFeature) { + // TODO Auto-generated method stub + return false; + } + } + + @Test + public void testApiDemos() throws IOException, XmlPullParserException { + findApiDemos(); + } + + private void findApiDemos() throws IOException, XmlPullParserException { + for (IAndroidTarget target : getSdk().getTargets()) { + String path = target.getPath(IAndroidTarget.SAMPLES); + File samples = new File(path); + if (samples.isDirectory()) { + File[] files = samples.listFiles(); + for (File file : files) { + if ("apidemos".equalsIgnoreCase(file.getName())) { + testSample(target, file); + return; + } + } + } + } + + fail("Failed to find ApiDemos!"); + } + + private void testSample(IAndroidTarget target, File sampleProject) throws IOException, XmlPullParserException { + AndroidTargetData data = getSdk().getTargetData(target); + if (data == null) { + fail("No AndroidData!"); + } + + LayoutLibrary layoutLib = data.getLayoutLibrary(); + if (layoutLib.getStatus() != LoadStatus.LOADED) { + fail("Fail to load the bridge: " + layoutLib.getLoadMessage()); + } + + FolderWrapper resFolder = new FolderWrapper(sampleProject, SdkConstants.FD_RES); + if (resFolder.exists() == false) { + fail("Sample project has no res folder!"); + } + + // look for the layout folder + File layoutFolder = new File(resFolder, SdkConstants.FD_RES_LAYOUT); + if (layoutFolder.isDirectory() == false) { + fail("Sample project has no layout folder!"); + } + + // first load the project's target framework resource + ResourceRepository framework = ResourceManager.getInstance().loadFrameworkResources(target); + + // now load the project resources + ResourceRepository project = new ResourceRepository(resFolder, false) { + @Override + protected ResourceItem createResourceItem(String name) { + return new ResourceItem(name); + } + + }; + + // Create a folder configuration that will be used for the rendering: + FolderConfiguration config = getConfiguration(); + + // get the configured resources + Map configuredFramework = framework.getConfiguredResources(config); + Map configuredProject = project.getConfiguredResources(config); + + boolean saveFiles = System.getenv("save_file") != null; + + // loop on the layouts and render them + File[] layouts = layoutFolder.listFiles(); + for (File layout : layouts) { + // create a parser for the layout file + TestParser parser = new TestParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(new FileReader(layout)); + + System.out.println("Rendering " + layout.getName()); + + ProjectCallBack projectCallBack = new ProjectCallBack(); + + ResourceResolver resolver = ResourceResolver + .create(configuredProject, configuredFramework, "Theme", false /* isProjectTheme */); + + HardwareConfig hardwareConfig = new HardwareConfig(320, 480, Density.MEDIUM, 160, // xdpi + 160, // ydpi + ScreenSize.NORMAL, ScreenOrientation.PORTRAIT, ScreenRound.NOTROUND, false /* + * software + * buttons + */); + + RenderSession session = layoutLib.createSession(new SessionParams(parser, RenderingMode.NORMAL, + null /* projectKey */, hardwareConfig, resolver, projectCallBack, 1, // minSdkVersion + 1, // targetSdkVersion + null // logger + )); + + if (session.getResult().isSuccess() == false) { + if (projectCallBack.mCustomViewAttempt == false) { + System.out.println("FAILED"); + fail(String.format("Rendering %1$s: %2$s", layout.getName(), session.getResult().getErrorMessage())); + } else { + System.out.println("Ignore custom views for now"); + } + } else { + if (saveFiles) { + File tmp = File.createTempFile(layout.getName(), ".png"); + ImageIO.write(session.getImage(), "png", tmp); + } + System.out.println("Success!"); + } + } + } + + /** + * Returns a config. This must be a valid config like a device would return. + * This is to prevent issues where some resources don't exist in all cases + * and not in the default (for instance only available in hdpi and mdpi but + * not in default). + * + * @return + */ + private FolderConfiguration getConfiguration() { + FolderConfiguration config = new FolderConfiguration(); + + // this matches an ADP1. + config.addQualifier(new SmallestScreenWidthQualifier(320)); + config.addQualifier(new ScreenWidthQualifier(320)); + config.addQualifier(new ScreenHeightQualifier(480)); + config.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL)); + config.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG)); + config.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT)); + config.addQualifier(new DensityQualifier(Density.MEDIUM)); + config.addQualifier(new TouchScreenQualifier(TouchScreen.FINGER)); + config.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN)); + config.addQualifier(new TextInputMethodQualifier(Keyboard.QWERTY)); + config.addQualifier(new NavigationStateQualifier(NavigationState.HIDDEN)); + config.addQualifier(new NavigationMethodQualifier(Navigation.TRACKBALL)); + config.addQualifier(new ScreenDimensionQualifier(480, 320)); + + config.updateScreenWidthAndHeight(); + + return config; + } +} diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/sampleProjects/SampleProjectTest.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/sampleProjects/SampleProjectTest.java index 1e18a2fa..042cd1ef 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/sampleProjects/SampleProjectTest.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/integration/tests/functests/sampleProjects/SampleProjectTest.java @@ -1,267 +1,266 @@ -/* - * 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 org.eclipse.andmore.integration.tests.functests.sampleProjects; - -import static org.junit.Assert.*; - -import com.android.SdkConstants; - -import org.eclipse.andmore.AdtUtils; -import org.eclipse.andmore.integration.tests.SdkLoadingTestCase; -import org.eclipse.andmore.internal.wizards.newproject.NewProjectCreator; -import org.eclipse.andmore.internal.wizards.newproject.NewProjectWizardState; -import org.eclipse.andmore.internal.wizards.newproject.NewProjectWizardState.Mode; - -import com.android.sdklib.IAndroidTarget; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jface.operation.IRunnableContext; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.swt.widgets.Display; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Test case that verifies all SDK sample projects can be imported, and built in - * Eclipse. - *

- * TODO: add support for deploying apps onto emulator and verifying successful - * execution there - * - */ -@Ignore -public class SampleProjectTest extends SdkLoadingTestCase { - - private static final Logger sLogger = Logger.getLogger(SampleProjectTest.class.getName()); - - /** - * Finds all samples projects in set SDK and verify they can be built in - * Eclipse. - *

- * TODO: add install and run on emulator test - * - * @throws CoreException - */ - @Test - public void testSamples() throws CoreException { - // TODO: For reporting purposes, it would be better if a separate test - // success or failure - // could be reported for each sample - IAndroidTarget[] targets = getSdk().getTargets(); - for (IAndroidTarget target : targets) { - doTestSamplesForTarget(target); - } - } - - private void doTestSamplesForTarget(IAndroidTarget target) throws CoreException { - String path = target.getPath(IAndroidTarget.SAMPLES); - File samples = new File(path); - if (samples.isDirectory()) { - File[] files = samples.listFiles(); - for (File file : files) { - if (file.isDirectory()) { - doTestSampleProject(file.getName(), file.getAbsolutePath(), target); - } - } - } - } - - /** - * Tests the sample project with the given name - * - * @param target - * - SDK target of project - * @param name - * - name of sample project to test - * @param path - * - absolute file system path - * @throws CoreException - */ - private void doTestSampleProject(String name, String path, IAndroidTarget target) throws CoreException { - IProject iproject = null; - try { - sLogger.log(Level.INFO, String.format("Testing sample %s for target %s", name, target.getName())); - - prepareProject(path, target); - - IRunnableContext context = new IRunnableContext() { - @Override - public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) - throws InvocationTargetException, InterruptedException { - runnable.run(new NullProgressMonitor()); - } - }; - NewProjectWizardState state = new NewProjectWizardState(Mode.SAMPLE); - state.projectName = name; - state.target = target; - state.packageName = "com.android.samples"; - state.activityName = name; - state.applicationName = name; - state.chosenSample = new File(path); - state.useDefaultLocation = false; - state.createActivity = false; - - NewProjectCreator creator = new NewProjectCreator(state, context); - creator.createAndroidProjects(); - iproject = validateProjectExists(name); - validateNoProblems(iproject); - } catch (CoreException e) { - sLogger.log(Level.SEVERE, String.format("Unexpected exception when creating sample project %s " - + "for target %s", name, target.getName())); - throw e; - } finally { - if (iproject != null) { - iproject.delete(false, true, new NullProgressMonitor()); - } - } - } - - private void prepareProject(String path, IAndroidTarget target) { - if (target.getVersion().isPreview()) { - // need to explicitly set preview's version in manifest for project - // to compile - final String manifestPath = path + File.separatorChar + SdkConstants.FN_ANDROID_MANIFEST_XML; - AndroidManifestWriter manifestWriter = AndroidManifestWriter.parse(manifestPath); - assertNotNull(String.format("could not read manifest %s", manifestPath), manifestWriter); - assertTrue(manifestWriter.setMinSdkVersion(target.getVersion().getApiString())); - } - } - - private IProject validateProjectExists(String name) { - IProject iproject = getIProject(name); - assertTrue(String.format("%s project not created", name), iproject.exists()); - assertTrue(String.format("%s project not opened", name), iproject.isOpen()); - return iproject; - } - - private IProject getIProject(String name) { - IProject iproject = ResourcesPlugin.getWorkspace().getRoot().getProject(name); - return iproject; - } - - private void validateNoProblems(IProject iproject) throws CoreException { - waitForBuild(iproject); - - boolean hasErrors = false; - StringBuilder failureBuilder = new StringBuilder(String.format("%s project has errors:", iproject.getName())); - IMarker[] markers = iproject.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); - if (markers != null && markers.length > 0) { - // the project has marker(s). even though they are "problem" we - // don't know their severity. so we loop on them and figure if they - // are warnings or errors - for (IMarker m : markers) { - int s = m.getAttribute(IMarker.SEVERITY, -1); - if (s == IMarker.SEVERITY_ERROR) { - hasErrors = true; - failureBuilder.append("\n"); - failureBuilder.append(m.getAttribute(IMarker.MESSAGE, "")); - } - } - } - failureBuilder.append("Project location: " + AdtUtils.getAbsolutePath(iproject)); - assertFalse(failureBuilder.toString(), hasErrors); - } - - /** - * Waits for build to complete. - * - * @param iproject - */ - private void waitForBuild(final IProject iproject) { - - final BuiltProjectDeltaVisitor deltaVisitor = new BuiltProjectDeltaVisitor(iproject); - IResourceChangeListener newBuildListener = new IResourceChangeListener() { - - @Override - public void resourceChanged(IResourceChangeEvent event) { - try { - event.getDelta().accept(deltaVisitor); - } catch (CoreException e) { - fail(); - } - } - - }; - iproject.getWorkspace().addResourceChangeListener(newBuildListener, IResourceChangeEvent.POST_BUILD); - - // poll build listener to determine when build is done - // loop max of 1200 times * 50 ms = 60 seconds - final int maxWait = 1200; - for (int i = 0; i < maxWait; i++) { - if (deltaVisitor.isProjectBuilt()) { - return; - } - try { - Thread.sleep(50); - } catch (InterruptedException e) { - // ignore - } - if (Display.getCurrent() != null) { - Display.getCurrent().readAndDispatch(); - } - } - - sLogger.log(Level.SEVERE, "expected build event never happened?"); - fail(String.format("Expected build event never happened for %s", iproject.getName())); - } - - /** - * Scans a given IResourceDelta looking for a "build event" change for given - * IProject - * - */ - private class BuiltProjectDeltaVisitor implements IResourceDeltaVisitor { - - private IProject mIProject; - private boolean mIsBuilt; - - public BuiltProjectDeltaVisitor(IProject iproject) { - mIProject = iproject; - mIsBuilt = false; - } - - @Override - public boolean visit(IResourceDelta delta) { - if (mIProject.equals(delta.getResource())) { - setBuilt(true); - return false; - } - return true; - } - - private synchronized void setBuilt(boolean b) { - mIsBuilt = b; - } - - public synchronized boolean isProjectBuilt() { - return mIsBuilt; - } - } -} +/* + * 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 org.eclipse.andmore.integration.tests.functests.sampleProjects; + +import static org.junit.Assert.*; + +import com.android.SdkConstants; + +import org.eclipse.andmore.AdtUtils; +import org.eclipse.andmore.integration.tests.SdkLoadingTestCase; +import org.eclipse.andmore.internal.wizards.newproject.NewProjectCreator; +import org.eclipse.andmore.internal.wizards.newproject.NewProjectWizardState; +import org.eclipse.andmore.internal.wizards.newproject.NewProjectWizardState.Mode; + +import com.android.sdklib.IAndroidTarget; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.swt.widgets.Display; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Test case that verifies all SDK sample projects can be imported, and built in + * Eclipse. + *

+ * TODO: add support for deploying apps onto emulator and verifying successful + * execution there + * + */ +@Ignore +public class SampleProjectTest extends SdkLoadingTestCase { + + private static final Logger sLogger = Logger.getLogger(SampleProjectTest.class.getName()); + + /** + * Finds all samples projects in set SDK and verify they can be built in + * Eclipse. + *

+ * TODO: add install and run on emulator test + * + * @throws CoreException + */ + @Test + public void testSamples() throws CoreException { + // TODO: For reporting purposes, it would be better if a separate test + // success or failure + // could be reported for each sample + for (IAndroidTarget target : getSdk().getTargets()) { + doTestSamplesForTarget(target); + } + } + + private void doTestSamplesForTarget(IAndroidTarget target) throws CoreException { + String path = target.getPath(IAndroidTarget.SAMPLES); + File samples = new File(path); + if (samples.isDirectory()) { + File[] files = samples.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + doTestSampleProject(file.getName(), file.getAbsolutePath(), target); + } + } + } + } + + /** + * Tests the sample project with the given name + * + * @param target + * - SDK target of project + * @param name + * - name of sample project to test + * @param path + * - absolute file system path + * @throws CoreException + */ + private void doTestSampleProject(String name, String path, IAndroidTarget target) throws CoreException { + IProject iproject = null; + try { + sLogger.log(Level.INFO, String.format("Testing sample %s for target %s", name, target.getName())); + + prepareProject(path, target); + + IRunnableContext context = new IRunnableContext() { + @Override + public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) + throws InvocationTargetException, InterruptedException { + runnable.run(new NullProgressMonitor()); + } + }; + NewProjectWizardState state = new NewProjectWizardState(Mode.SAMPLE); + state.projectName = name; + state.target = target; + state.packageName = "com.android.samples"; + state.activityName = name; + state.applicationName = name; + state.chosenSample = new File(path); + state.useDefaultLocation = false; + state.createActivity = false; + + NewProjectCreator creator = new NewProjectCreator(state, context); + creator.createAndroidProjects(); + iproject = validateProjectExists(name); + validateNoProblems(iproject); + } catch (CoreException e) { + sLogger.log(Level.SEVERE, String.format("Unexpected exception when creating sample project %s " + + "for target %s", name, target.getName())); + throw e; + } finally { + if (iproject != null) { + iproject.delete(false, true, new NullProgressMonitor()); + } + } + } + + private void prepareProject(String path, IAndroidTarget target) { + if (target.getVersion().isPreview()) { + // need to explicitly set preview's version in manifest for project + // to compile + final String manifestPath = path + File.separatorChar + SdkConstants.FN_ANDROID_MANIFEST_XML; + AndroidManifestWriter manifestWriter = AndroidManifestWriter.parse(manifestPath); + assertNotNull(String.format("could not read manifest %s", manifestPath), manifestWriter); + assertTrue(manifestWriter.setMinSdkVersion(target.getVersion().getApiString())); + } + } + + private IProject validateProjectExists(String name) { + IProject iproject = getIProject(name); + assertTrue(String.format("%s project not created", name), iproject.exists()); + assertTrue(String.format("%s project not opened", name), iproject.isOpen()); + return iproject; + } + + private IProject getIProject(String name) { + IProject iproject = ResourcesPlugin.getWorkspace().getRoot().getProject(name); + return iproject; + } + + private void validateNoProblems(IProject iproject) throws CoreException { + waitForBuild(iproject); + + boolean hasErrors = false; + StringBuilder failureBuilder = new StringBuilder(String.format("%s project has errors:", iproject.getName())); + IMarker[] markers = iproject.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); + if (markers != null && markers.length > 0) { + // the project has marker(s). even though they are "problem" we + // don't know their severity. so we loop on them and figure if they + // are warnings or errors + for (IMarker m : markers) { + int s = m.getAttribute(IMarker.SEVERITY, -1); + if (s == IMarker.SEVERITY_ERROR) { + hasErrors = true; + failureBuilder.append("\n"); + failureBuilder.append(m.getAttribute(IMarker.MESSAGE, "")); + } + } + } + failureBuilder.append("Project location: " + AdtUtils.getAbsolutePath(iproject)); + assertFalse(failureBuilder.toString(), hasErrors); + } + + /** + * Waits for build to complete. + * + * @param iproject + */ + private void waitForBuild(final IProject iproject) { + + final BuiltProjectDeltaVisitor deltaVisitor = new BuiltProjectDeltaVisitor(iproject); + IResourceChangeListener newBuildListener = new IResourceChangeListener() { + + @Override + public void resourceChanged(IResourceChangeEvent event) { + try { + event.getDelta().accept(deltaVisitor); + } catch (CoreException e) { + fail(); + } + } + + }; + iproject.getWorkspace().addResourceChangeListener(newBuildListener, IResourceChangeEvent.POST_BUILD); + + // poll build listener to determine when build is done + // loop max of 1200 times * 50 ms = 60 seconds + final int maxWait = 1200; + for (int i = 0; i < maxWait; i++) { + if (deltaVisitor.isProjectBuilt()) { + return; + } + try { + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore + } + if (Display.getCurrent() != null) { + Display.getCurrent().readAndDispatch(); + } + } + + sLogger.log(Level.SEVERE, "expected build event never happened?"); + fail(String.format("Expected build event never happened for %s", iproject.getName())); + } + + /** + * Scans a given IResourceDelta looking for a "build event" change for given + * IProject + * + */ + private class BuiltProjectDeltaVisitor implements IResourceDeltaVisitor { + + private IProject mIProject; + private boolean mIsBuilt; + + public BuiltProjectDeltaVisitor(IProject iproject) { + mIProject = iproject; + mIsBuilt = false; + } + + @Override + public boolean visit(IResourceDelta delta) { + if (mIProject.equals(delta.getResource())) { + setBuilt(true); + return false; + } + return true; + } + + private synchronized void setBuilt(boolean b) { + mIsBuilt = b; + } + + public synchronized boolean isProjectBuilt() { + return mIsBuilt; + } + } +} diff --git a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/internal/build/AaptParserTest.java b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/internal/build/AaptParserTest.java index 7361c690..28e04333 100644 --- a/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/internal/build/AaptParserTest.java +++ b/android-core/plugins/org.eclipse.andmore.integration.tests/src/org/eclipse/andmore/internal/build/AaptParserTest.java @@ -1,212 +1,212 @@ -/* - * Copyright (C) 2011 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 org.eclipse.andmore.internal.build; - -import static org.junit.Assert.*; - -import org.eclipse.andmore.AndmoreAndroidConstants; -import org.eclipse.andmore.AndmoreAndroidPlugin; -import org.eclipse.andmore.internal.build.AaptParser; -import org.eclipse.andmore.internal.editors.layout.refactoring.AdtProjectTest; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; -import java.util.Collections; -import java.util.List; - -public class AaptParserTest extends AdtProjectTest { - - @Test - public void testBasic() throws Exception { - // Test the "at 'property' with value 'value' range matching included - // with most aapt errors - checkRanges("quickfix1.xml", "res/layout/quickfix1.xml", - "quickfix1.xml:7: error: Error: No resource found that matches the given name (at" - + " 'text' with value '@string/firststring').", "android:text=\"^@string/firststring\"", - "android:text=\"@string/firststring^\""); - } - - @Test - public void testRange1() throws Exception { - // Check that when the actual aapt error occurs on a line later than the - // original error - // line, the forward search which looks for a value match does not stop - // on an - // earlier line that happens to have the same value prefix - checkRanges("aapterror1.xml", "res/layout/aapterror1.xml", - "aapterror1.xml:5: error: Error: Integer types not allowed (at " - + "'layout_marginBottom' with value '50').", "marginBottom=\"^50\"", "marginBottom=\"50^\""); - } - - @Test - public void testRange2() throws Exception { - // Check that when we have a duplicate resource error, we highlight both - // the original - // property and the original definition. - // This tests the second, duplicate declaration ration. - checkRanges("aapterror2.xml", "res/values/aapterror2.xml", - "aapterror2.xml:7: error: Resource entry repeatedStyle1 already has bag item " + "android:gravity.", - "bottom", "bottom"); - } - - @Test - @Ignore - public void testRange3() throws Exception { - // Check that when we have a duplicate resource error, we highlight both - // the original - // property and the original definition. - // This tests the original definition. Note that we don't have enough - // position info - // so we simply highlight the whitespace portion of the line. - checkRanges("aapterror2.xml", "res/values/aapterror2.xml", "aapterror2.xml:4: Originally defined here.", - "^left", "left^"); - } - - @Test - public void testRange4() throws Exception { - // Check for aapt error which occurs when the attribute name in an item - // style declaration - // is nonexistent - checkRanges("aapterror3.xml", "res/values/aapterror3.xml", - "aapterror3.xml:4: error: Error: No resource found that matches the given name: " - + "attr 'nonexistent'.", "5", - "5"); - } - - @Test - public void testRange5() throws Exception { - // Test missing resource name - checkRanges("aapterror4.xml", "res/values/aapterror4.xml", - "aapterror4.xml:3: error: A 'name' attribute is required for