1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.sdklib.internal.repository; 18 19 import com.android.annotations.VisibleForTesting; 20 import com.android.annotations.VisibleForTesting.Visibility; 21 import com.android.sdklib.SdkConstants; 22 import com.android.sdklib.SdkManager; 23 import com.android.sdklib.internal.repository.Archive.Arch; 24 import com.android.sdklib.internal.repository.Archive.Os; 25 26 import org.w3c.dom.Node; 27 28 import java.io.File; 29 import java.util.HashSet; 30 import java.util.Map; 31 import java.util.Properties; 32 import java.util.Set; 33 34 /** 35 * Represents a platform-tool XML node in an SDK repository. 36 */ 37 public class PlatformToolPackage extends Package { 38 39 /** The value returned by {@link PlatformToolPackage#installId()}. */ 40 public static final String INSTALL_ID = "platform-tools"; //$NON-NLS-1$ 41 42 /** 43 * Creates a new platform-tool package from the attributes and elements of the given XML node. 44 * This constructor should throw an exception if the package cannot be created. 45 * 46 * @param source The {@link SdkSource} where this is loaded from. 47 * @param packageNode The XML element being parsed. 48 * @param nsUri The namespace URI of the originating XML document, to be able to deal with 49 * parameters that vary according to the originating XML schema. 50 * @param licenses The licenses loaded from the XML originating document. 51 */ 52 PlatformToolPackage(SdkSource source, Node packageNode, 53 String nsUri, Map<String,String> licenses) { 54 super(source, packageNode, nsUri, licenses); 55 } 56 57 /** 58 * Manually create a new package with one archive and the given attributes or properties. 59 * This is used to create packages from local directories in which case there must be 60 * one archive which URL is the actual target location. 61 * <p/> 62 * By design, this creates a package with one and only one archive. 63 */ 64 static Package create( 65 SdkSource source, 66 Properties props, 67 int revision, 68 String license, 69 String description, 70 String descUrl, 71 Os archiveOs, 72 Arch archiveArch, 73 String archiveOsPath) { 74 75 PlatformToolPackage ptp = new PlatformToolPackage(source, props, revision, license, 76 description, descUrl, archiveOs, archiveArch, archiveOsPath); 77 78 File platformToolsFolder = new File(archiveOsPath); 79 String error = null; 80 if (!platformToolsFolder.isDirectory()) { 81 error = "platform-tools folder is missing"; 82 } else { 83 File[] files = platformToolsFolder.listFiles(); 84 if (files == null || files.length == 0) { 85 error = "platform-tools folder is empty"; 86 } else { 87 Set<String> names = new HashSet<String>(); 88 for (File file : files) { 89 names.add(file.getName()); 90 } 91 for (String name : new String[] { SdkConstants.FN_ADB, 92 SdkConstants.FN_AAPT, 93 SdkConstants.FN_AIDL, 94 SdkConstants.FN_DX } ) { 95 if (!names.contains(name)) { 96 if (error == null) { 97 error = "platform-tools folder is missing "; 98 } else { 99 error += ", "; 100 } 101 error += name; 102 } 103 } 104 } 105 } 106 107 if (error != null) { 108 String shortDesc = ptp.getShortDescription() + " [*]"; //$NON-NLS-1$ 109 110 String longDesc = String.format( 111 "Broken Platform-Tools Package: %1$s\n" + 112 "[*] Package cannot be used due to error: %2$s", 113 description, 114 error); 115 116 BrokenPackage ba = new BrokenPackage(props, shortDesc, longDesc, 117 IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED, 118 IExactApiLevelDependency.API_LEVEL_INVALID, 119 archiveOsPath); 120 return ba; 121 } 122 123 124 return ptp; 125 } 126 127 @VisibleForTesting(visibility=Visibility.PRIVATE) 128 protected PlatformToolPackage( 129 SdkSource source, 130 Properties props, 131 int revision, 132 String license, 133 String description, 134 String descUrl, 135 Os archiveOs, 136 Arch archiveArch, 137 String archiveOsPath) { 138 super(source, 139 props, 140 revision, 141 license, 142 description, 143 descUrl, 144 archiveOs, 145 archiveArch, 146 archiveOsPath); 147 } 148 149 /** 150 * Returns a string identifier to install this package from the command line. 151 * For platform-tools, we use "platform-tools" since this package type is unique. 152 * <p/> 153 * {@inheritDoc} 154 */ 155 @Override 156 public String installId() { 157 return INSTALL_ID; 158 } 159 160 /** 161 * Returns a description of this package that is suitable for a list display. 162 * <p/> 163 * {@inheritDoc} 164 */ 165 @Override 166 public String getListDescription() { 167 return String.format("Android SDK Platform-tools%1$s", 168 isObsolete() ? " (Obsolete)" : ""); 169 } 170 171 /** 172 * Returns a short description for an {@link IDescription}. 173 */ 174 @Override 175 public String getShortDescription() { 176 return String.format("Android SDK Platform-tools, revision %1$d%2$s", 177 getRevision(), 178 isObsolete() ? " (Obsolete)" : ""); 179 } 180 181 /** Returns a long description for an {@link IDescription}. */ 182 @Override 183 public String getLongDescription() { 184 String s = getDescription(); 185 if (s == null || s.length() == 0) { 186 s = getShortDescription(); 187 } 188 189 if (s.indexOf("revision") == -1) { 190 s += String.format("\nRevision %1$d%2$s", 191 getRevision(), 192 isObsolete() ? " (Obsolete)" : ""); 193 } 194 195 return s; 196 } 197 198 /** 199 * Computes a potential installation folder if an archive of this package were 200 * to be installed right away in the given SDK root. 201 * <p/> 202 * A "tool" package should always be located in SDK/tools. 203 * 204 * @param osSdkRoot The OS path of the SDK root folder. 205 * @param sdkManager An existing SDK manager to list current platforms and addons. 206 * @return A new {@link File} corresponding to the directory to use to install this package. 207 */ 208 @Override 209 public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) { 210 return new File(osSdkRoot, SdkConstants.FD_PLATFORM_TOOLS); 211 } 212 213 @Override 214 public boolean sameItemAs(Package pkg) { 215 // only one platform-tool package so any platform-tool package is the same item. 216 return pkg instanceof PlatformToolPackage; 217 } 218 219 /** 220 * Hook called right before an archive is installed. 221 * This is used here to stop ADB before trying to replace the platform-tool package. 222 * 223 * @param archive The archive that will be installed 224 * @param monitor The {@link ITaskMonitor} to display errors. 225 * @param osSdkRoot The OS path of the SDK root folder. 226 * @param installFolder The folder where the archive will be installed. Note that this 227 * is <em>not</em> the folder where the archive was temporary 228 * unzipped. The installFolder, if it exists, contains the old 229 * archive that will soon be replaced by the new one. 230 * @return True if installing this archive shall continue, false if it should be skipped. 231 */ 232 @Override 233 public boolean preInstallHook(Archive archive, ITaskMonitor monitor, 234 String osSdkRoot, File installFolder) { 235 AdbWrapper aw = new AdbWrapper(osSdkRoot, monitor); 236 aw.stopAdb(); 237 return super.preInstallHook(archive, monitor, osSdkRoot, installFolder); 238 } 239 240 } 241